This project has retired. For details please refer to its Attic page.
EntityQuery.java

EntityQuery.java

/*
 * 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);
		}
	}
	
}