/* | |
* Copyright 2001-2008 The Apache Software Foundation. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
* | |
*/ | |
package org.apache.juddi.query; | |
import java.util.List; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import javax.persistence.EntityManager; | |
import javax.persistence.Query; | |
import org.apache.commons.configuration.ConfigurationException; | |
import org.apache.commons.logging.Log; | |
import org.apache.commons.logging.LogFactory; | |
import org.uddi.api_v3.ListDescription; | |
import org.apache.juddi.config.AppConfig; | |
import org.apache.juddi.config.Property; | |
import org.apache.juddi.model.TempKey; | |
import org.apache.juddi.query.util.DynamicQuery; | |
/** | |
* @author <a href="mailto:jfaath@apache.org">Jeff Faath</a> | |
*/ | |
public abstract class EntityQuery { | |
private static Log log = LogFactory.getLog(EntityQuery.class); | |
public static final String KEY_NAME = "entityKey"; | |
public static final String TEMP_ENTITY_NAME = "TempKey"; | |
public static final String TEMP_ENTITY_ALIAS = "tk"; | |
public static final String TEMP_ENTITY_PK_TXID_NAME = TEMP_ENTITY_ALIAS + ".pk.txId"; | |
public static final String TEMP_ENTITY_PK_KEY_NAME = TEMP_ENTITY_ALIAS + ".pk.entityKey"; | |
public static final String SIGNATURE_FIELD = "signatures"; | |
public static final int DEFAULT_MAXROWS = 1000; | |
public static final int DEFAULT_MAXINCLAUSE = 1000; | |
// TODO: make this alias creator a little more unique | |
public static String buildAlias(String entityName) { | |
if (entityName == null || entityName.length() == 0) | |
return "x"; | |
return entityName.substring(0, entityName.length() - 3) + "_"; | |
} | |
/* | |
* Used to retrieve the final results of find operations. Handles paging as specified by user. | |
* | |
* TODO: This query will use an IN clause, however, it is not restricted per the global parameter. This is so the query can | |
* take advantage of sorting through SQL. The fix would be to apply the parameter, but only if the IN list is greater than the | |
* parameter. In this case, sorting would have to be done in java. | |
* | |
*/ | |
public static List<?> getPagedResult(EntityManager em, DynamicQuery dynamicQry, Integer maxRowsUser, Integer listHead, ListDescription listDesc) { | |
int maxRows = DEFAULT_MAXROWS; | |
try { | |
maxRows = AppConfig.getConfiguration().getInteger(Property.JUDDI_MAX_ROWS, DEFAULT_MAXROWS); | |
} | |
catch(ConfigurationException ce) { | |
log.error("Configuration exception occurred retrieving: " + Property.JUDDI_MAX_ROWS); | |
} | |
if (maxRowsUser != null && maxRowsUser > 0) { | |
if (maxRowsUser < maxRows) | |
maxRows = maxRowsUser; | |
} | |
if (listHead == null || listHead <= 0) | |
listHead = 1; | |
Query qry = dynamicQry.buildJPAQuery(em); | |
List<Object> result = new ArrayList<Object>(); | |
//Filter out non-unique results | |
for (Object object : qry.getResultList()) { | |
if (!result.contains(object)) { | |
result.add(object); | |
} | |
} | |
int resultSize = result.size(); | |
if (listDesc != null) { | |
listDesc.setActualCount(resultSize); | |
listDesc.setListHead(listHead); | |
} | |
int startIndex = listHead - 1; | |
if (startIndex >= resultSize) { | |
if (listDesc != null) | |
listDesc.setIncludeCount(0); | |
return Collections.emptyList(); | |
} | |
else { | |
int endIndex = Math.min(startIndex + maxRows, resultSize); | |
if (listDesc != null) | |
listDesc.setIncludeCount(endIndex - startIndex); | |
List<Object> subList = new ArrayList<Object>(endIndex); | |
for (int i=startIndex; i< endIndex; i++) { | |
subList.add(result.get(i)); | |
} | |
return subList; | |
} | |
} | |
/* | |
* Used for all the find operation sub-queries. Restricts size of the IN clause based on global parameter | |
*/ | |
@SuppressWarnings("unchecked") | |
public static List<Object> getQueryResult(EntityManager em, DynamicQuery dynamicQry, List<?> keysIn, String inListTerm) { | |
List<Object> result = new ArrayList<Object>(0); | |
// If keysIn is null, then no IN list is applied to the query - we simply need to run the query. Otherwise, the IN list is chunked based on | |
// the application property. | |
if (keysIn == null) { | |
if (log.isDebugEnabled()) log.debug(dynamicQry); | |
Query qry = dynamicQry.buildJPAQuery(em); | |
result = qry.getResultList(); | |
} | |
else { | |
int maxInClause = DEFAULT_MAXINCLAUSE; | |
try { | |
maxInClause = AppConfig.getConfiguration().getInteger(Property.JUDDI_MAX_IN_CLAUSE, DEFAULT_MAXINCLAUSE); | |
} | |
catch(ConfigurationException ce) { | |
log.error("Configuration exception occurred retrieving: " + Property.JUDDI_MAX_IN_CLAUSE); | |
} | |
if (keysIn.isEmpty()) { | |
Query qry = dynamicQry.buildJPAQuery(em); | |
List<Object> resultChunk = qry.getResultList(); | |
result.addAll(resultChunk); | |
} else { | |
int inParamsLeft = keysIn.size(); | |
int startIndex = 0; | |
while(inParamsLeft > 0) { | |
int endIndex = startIndex + Math.min(inParamsLeft, maxInClause); | |
List<Object> subKeysIn = new ArrayList<Object>(endIndex); | |
for (int i=startIndex; i< endIndex; i++) { | |
subKeysIn.add(keysIn.get(i)); | |
} | |
dynamicQry.appendInListWithAnd(inListTerm, subKeysIn); | |
log.debug(dynamicQry); | |
Query qry = dynamicQry.buildJPAQuery(em); | |
List<Object> resultChunk = qry.getResultList(); | |
result.addAll(resultChunk); | |
inParamsLeft = inParamsLeft - (endIndex - startIndex); | |
startIndex = endIndex; | |
} | |
} | |
} | |
return result; | |
} | |
public static void storeIntermediateKeySetResults (EntityManager em, String txId, List<?> keysIn) { | |
for (Object key : keysIn) { | |
TempKey tempKey = new TempKey(); | |
tempKey.setPk(txId,key.toString()); | |
em.persist(tempKey); | |
} | |
} | |
} |