001 /* 002 * Cumulus4j - Securing your data in the cloud - http://cumulus4j.org 003 * Copyright (C) 2011 NightLabs Consulting GmbH 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 package org.cumulus4j.store.query; 019 020 import java.util.ArrayList; 021 import java.util.Collection; 022 import java.util.Collections; 023 import java.util.HashSet; 024 import java.util.List; 025 import java.util.Set; 026 027 import javax.jdo.PersistenceManager; 028 029 import org.cumulus4j.store.Cumulus4jStoreManager; 030 import org.cumulus4j.store.model.ClassMeta; 031 import org.cumulus4j.store.model.DataEntry; 032 import org.datanucleus.ClassLoaderResolver; 033 import org.datanucleus.identity.IdentityUtils; 034 import org.datanucleus.store.ExecutionContext; 035 036 /** 037 * Helper methods for querying. 038 */ 039 public class QueryHelper { 040 041 /** 042 * Access the data entry ids for a candidate. 043 * @param pmData PersistenceManager for the backend data 044 * @param ec ExecutionContext 045 * @param candidateCls Candidate class 046 * @param subclasses Whether to include subclasses 047 * @return The data entry ids 048 */ 049 public static Set<Long> getAllDataEntryIdsForCandidate(PersistenceManager pmData, ExecutionContext ec, Class candidateCls, boolean subclasses) { 050 javax.jdo.Query q = pmData.newQuery(DataEntry.class); 051 q.setResult("this.dataEntryID"); 052 053 Object queryParam; 054 Set<ClassMeta> classMetas = QueryHelper.getCandidateClassMetas((Cumulus4jStoreManager) ec.getStoreManager(), 055 ec, candidateCls, subclasses); 056 if (classMetas.size() == 1) { 057 q.setFilter("this.classMeta == :classMeta"); 058 queryParam = classMetas.iterator().next(); 059 } 060 else { 061 q.setFilter(":classMetas.contains(this.classMeta)"); 062 queryParam = classMetas; 063 } 064 065 @SuppressWarnings("unchecked") 066 Collection<Object[]> c = (Collection<Object[]>) q.execute(queryParam); 067 Set<Long> resultList = new HashSet<Long>(c.size()); 068 for (Object[] oa : c) { 069 resultList.add((Long)oa[0]); 070 } 071 q.closeAll(); 072 return resultList; 073 } 074 075 /** 076 * Convenience method to return the persistent objects for the classes with the provided ClassMetas. 077 * @param pmData PersistenceManager for the backend data 078 * @param ec ExecutionContext 079 * @param candidateClassMetas The class metas defining the required classes 080 * @return The persistent objects 081 */ 082 public static List<Object> getAllPersistentObjectsForCandidateClasses(PersistenceManager pmData, ExecutionContext ec, 083 Set<ClassMeta> candidateClassMetas) 084 { 085 javax.jdo.Query q = pmData.newQuery(DataEntry.class); 086 q.setResult("this.classMeta, this.objectID"); 087 088 Object queryParam; 089 if (candidateClassMetas.size() == 1) { 090 q.setFilter("this.classMeta == :classMeta"); 091 queryParam = candidateClassMetas.iterator().next(); 092 } 093 else { 094 q.setFilter(":classMetas.contains(this.classMeta)"); 095 queryParam = candidateClassMetas; 096 } 097 098 @SuppressWarnings("unchecked") 099 Collection<Object[]> c = (Collection<Object[]>) q.execute(queryParam); 100 List<Object> resultList = new ArrayList<Object>(c.size()); 101 for (Object[] oa : c) { 102 ClassMeta classMeta = (ClassMeta) oa[0]; 103 String objectIDString = (String) oa[1]; 104 Object obj = IdentityUtils.getObjectFromIdString(objectIDString, classMeta.getDataNucleusClassMetaData(ec), ec, true); 105 resultList.add(obj); 106 } 107 q.closeAll(); 108 return resultList; 109 } 110 111 /** 112 * Convenience method to return the ClassMeta objects for the specified class (and subclasses if required). 113 * @param storeMgr Cumulus4J StoreManager 114 * @param ec ExecutionContext 115 * @param candidateClass The class required 116 * @param withSubclasses Whether to return subclasses too 117 * @return The ClassMeta objects 118 */ 119 public static Set<ClassMeta> getCandidateClassMetas(Cumulus4jStoreManager storeMgr, ExecutionContext ec, 120 Class<?> candidateClass, boolean withSubclasses) 121 { 122 Set<? extends Class<?>> candidateClasses; 123 if (withSubclasses) { 124 ClassLoaderResolver clr = ec.getClassLoaderResolver(); 125 HashSet<String> classNames = storeMgr.getSubClassesForClass(candidateClass.getName(), true, clr); 126 Set<Class<?>> classes = new HashSet<Class<?>>(classNames.size() + 1); 127 classes.add(candidateClass); 128 for (String className : classNames) { 129 Class<?> clazz = clr.classForName(className); 130 classes.add(clazz); 131 } 132 candidateClasses = classes; 133 } 134 else 135 candidateClasses = Collections.singleton(candidateClass); 136 137 Set<ClassMeta> candidateClassMetas = new HashSet<ClassMeta>(candidateClasses.size()); 138 for (Class<?> c : candidateClasses) { 139 ClassMeta cm = storeMgr.getClassMeta(ec, c); 140 candidateClassMetas.add(cm); 141 } 142 143 return candidateClassMetas; 144 } 145 }