View Javadoc
1   /*
2    * Copyright 2001-2008 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   */
17  
18  package org.apache.juddi.query;
19  
20  import java.util.Collections;
21  import java.util.List;
22  import java.util.UUID;
23  
24  import javax.persistence.EntityManager;
25  
26  import org.apache.commons.configuration.ConfigurationException;
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.apache.juddi.config.AppConfig;
30  import org.apache.juddi.config.Property;
31  import org.apache.juddi.query.util.DynamicQuery;
32  import org.apache.juddi.query.util.FindQualifiers;
33  import org.uddi.v3_service.DispositionReportFaultMessage;
34  import org.uddi.api_v3.ListDescription;
35  
36  /**
37   * The "select" method retrieves all the entities for the input key list and sorts according to the user settings.  Paging is taken into account when retrieving 
38   * the results.  The result is a list of the entity objects containing all top level elements (restricted to the given page). 
39   * 
40   * NOTE:  Results usually need multiple one-to-many collections to be fetched.  Although this could be done in one query with eager fetching, this strategy is not
41   * recommended as it will lead to a potentially large Cartesian product.  Therefore, the collections are initialized in separate queries during the mapping 
42   * stage.  If the returned results are small (maxRows parameters is set appropriately), a single query is likely faster, but probably not by enough to consider 
43   * the optimization under these conditions.
44   * 
45   * @author <a href="mailto:jfaath@apache.org">Jeff Faath</a>
46   */
47  public class FetchTModelsQuery extends TModelQuery {
48  
49  	private static final Log log = LogFactory.getLog(FetchTModelsQuery.class);
50  
51  	protected static final String selectSQL;
52  
53  	static {
54  		StringBuilder sql = new StringBuilder(200);
55  		sql.append("select " + ENTITY_ALIAS + " from " + ENTITY_NAME + " " + ENTITY_ALIAS + " ");
56  		selectSQL = sql.toString();
57  	}
58  	
59  	public static List<?> select(EntityManager em, FindQualifiers fq, List<?> keysIn, Integer maxRowsUser, Integer listHead, ListDescription listDesc, DynamicQuery.Parameter... restrictions) throws DispositionReportFaultMessage {
60  		
61  		// If keysIn is null or empty, then nothing to fetch.
62  		if ((keysIn == null) || (keysIn.size() == 0))
63  			return Collections.emptyList();
64  		int maxRows = DEFAULT_MAXROWS;
65  		try {
66  			maxRows = AppConfig.getConfiguration().getInteger(Property.JUDDI_MAX_ROWS, DEFAULT_MAXROWS);
67  		}
68  		catch(ConfigurationException ce) {
69  			log.error("Configuration exception occurred retrieving: " + Property.JUDDI_MAX_ROWS);
70  		}
71  		DynamicQuery dynamicQry = new DynamicQuery(selectSQL);
72  		if (keysIn.size() > maxRows) {
73  			UUID uuid = UUID.randomUUID();
74  			storeIntermediateKeySetResults(em, uuid.toString(), keysIn);
75  			appendTempTable(dynamicQry);
76  			appendSortTables(dynamicQry);
77  			appendTempJoin(dynamicQry, uuid.toString());
78  		}
79  		else {
80  			appendSortTables(dynamicQry);
81  			dynamicQry.appendInListWithAnd(ENTITY_ALIAS + "." + KEY_NAME, keysIn);
82  		}
83  		if (restrictions != null && restrictions.length > 0)
84  			dynamicQry.AND().pad().appendGroupedAnd(restrictions);
85  		
86  		appendSortCriteria(dynamicQry, fq);
87  
88  		log.debug(dynamicQry);
89  		
90  		return getPagedResult(em, dynamicQry, maxRowsUser, listHead, listDesc);
91  	}
92  	
93  	private static void appendTempTable(DynamicQuery qry) {
94  		qry.comma().append(TEMP_ENTITY_NAME + " " +  TEMP_ENTITY_ALIAS );
95  	}
96  	
97  	private static void appendTempJoin(DynamicQuery qry, String uuid) {
98  		qry.pad().AND().pad().append(TEMP_ENTITY_PK_KEY_NAME).append(DynamicQuery.PREDICATE_EQUALS);
99  		qry.append(ENTITY_ALIAS + "." + KEY_NAME);
100 		qry.pad().AND().pad().append(TEMP_ENTITY_PK_TXID_NAME).append(DynamicQuery.PREDICATE_EQUALS);
101 		qry.append("'" + uuid + "'").pad();
102 	}
103 	
104 	private static void appendSortTables(DynamicQuery qry) {
105 		// TModels don't need the join table, the single name is in the main table.
106 		qry.WHERE().pad().append("1=1").pad();
107 	}
108 	
109 	/*
110 	 *	Default ordering is name ascending and date descending.  If a name item is set, then it will always go first.  If only a date item is set, then date will
111 	 *  go first, and the name sort will occur second in ascending order.
112 	 */
113 	private static void appendSortCriteria(DynamicQuery qry, FindQualifiers fq) {
114 		
115 		String nameTerm = ENTITY_ALIAS + ".name";
116 		if (fq.isCaseInsensitiveSort()) {
117 			// See JUDDI-785
118 			log.info("jUDDI does not support caseInsensitive sort, as JPA does not support sortBy "
119 					+ "with UPPER or LOWER, see https://issues.apache.org/jira/browse/OPENJPA-1817. "
120 					+ "A work around is to do a caseInsentive Match.");
121 			//nameTerm = "upper(" + nameTerm + ")";
122 		}
123 		String dateTerm = ENTITY_ALIAS + ".modified";
124 
125 		String orderClause = nameTerm + " " + DynamicQuery.SORT_ASC + ", " + dateTerm + " " + DynamicQuery.SORT_DESC;
126 		if (fq.isSortByNameAsc()) {
127 			if (fq.isSortByDateAsc())
128 				orderClause = nameTerm + " " + DynamicQuery.SORT_ASC + ", " + dateTerm + " " + DynamicQuery.SORT_ASC;
129 		}
130 		else if (fq.isSortByNameDesc()) {
131 			if (fq.isSortByDateAsc())
132 				orderClause = nameTerm + " " + DynamicQuery.SORT_DESC + ", " + dateTerm + " " + DynamicQuery.SORT_ASC;
133 			else
134 				orderClause = nameTerm + " " + DynamicQuery.SORT_DESC + ", " + dateTerm + " " + DynamicQuery.SORT_DESC;
135 		}
136 		else if (fq.isSortByDateAsc())
137 			orderClause =  dateTerm + " " + DynamicQuery.SORT_ASC + ", " +  nameTerm + " " + DynamicQuery.SORT_ASC;
138 		else if (fq.isSortByDateDesc())
139 			orderClause =  dateTerm + " " + DynamicQuery.SORT_DESC + ", " +  nameTerm + " " + DynamicQuery.SORT_ASC;
140 			
141 		qry.ORDERBY().pad();
142 		qry.append(orderClause);
143 		qry.pad();
144 	}
145 
146 }