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  package org.apache.juddi.api.impl;
18  
19  import java.util.ArrayList;
20  import java.util.Date;
21  import java.util.LinkedList;
22  import java.util.List;
23  
24  import javax.persistence.EntityManager;
25  import javax.xml.ws.Holder;
26  import org.apache.commons.configuration.ConfigurationException;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.apache.juddi.config.AppConfig;
31  import org.apache.juddi.config.Property;
32  import org.apache.juddi.mapping.MappingModelToApi;
33  import org.apache.juddi.model.BindingTemplate;
34  import org.apache.juddi.query.FetchBindingTemplatesQuery;
35  import org.apache.juddi.query.FetchBusinessEntitiesQuery;
36  import org.apache.juddi.query.FetchBusinessServicesQuery;
37  import org.apache.juddi.query.FetchTModelsQuery;
38  import org.apache.juddi.query.FindBindingByCategoryGroupQuery;
39  import org.apache.juddi.query.FindBindingByCategoryQuery;
40  import org.apache.juddi.query.FindBindingByTModelKeyQuery;
41  import org.apache.juddi.query.FindBusinessByCategoryGroupQuery;
42  import org.apache.juddi.query.FindBusinessByCategoryQuery;
43  import org.apache.juddi.query.FindBusinessByCombinedCategoryQuery;
44  import org.apache.juddi.query.FindBusinessByDiscoveryURLQuery;
45  import org.apache.juddi.query.FindBusinessByIdentifierQuery;
46  import org.apache.juddi.query.FindBusinessByNameQuery;
47  import org.apache.juddi.query.FindBusinessByTModelKeyQuery;
48  import org.apache.juddi.query.FindServiceByCategoryGroupQuery;
49  import org.apache.juddi.query.FindServiceByCategoryQuery;
50  import org.apache.juddi.query.FindServiceByCombinedCategoryQuery;
51  import org.apache.juddi.query.FindServiceByNameQuery;
52  import org.apache.juddi.query.FindServiceByTModelKeyQuery;
53  import org.apache.juddi.query.FindTModelByCategoryGroupQuery;
54  import org.apache.juddi.query.FindTModelByCategoryQuery;
55  import org.apache.juddi.query.FindTModelByIdentifierQuery;
56  import org.apache.juddi.query.FindTModelByNameQuery;
57  import org.apache.juddi.query.util.FindQualifiers;
58  import org.apache.juddi.v3.error.ErrorMessage;
59  import org.apache.juddi.v3.error.InvalidKeyPassedException;
60  import org.uddi.api_v3.BindingDetail;
61  import org.uddi.api_v3.BusinessList;
62  import org.uddi.api_v3.Direction;
63  import org.uddi.api_v3.FindBinding;
64  import org.uddi.api_v3.FindBusiness;
65  import org.uddi.api_v3.FindRelatedBusinesses;
66  import org.uddi.api_v3.FindService;
67  import org.uddi.api_v3.FindTModel;
68  import org.uddi.api_v3.ListDescription;
69  import org.uddi.api_v3.Name;
70  import org.uddi.api_v3.RelatedBusinessesList;
71  import org.uddi.api_v3.ServiceList;
72  import org.uddi.api_v3.TModelBag;
73  import org.uddi.api_v3.TModelList;
74  import org.uddi.v3_service.DispositionReportFaultMessage;
75  
76  /**Co
77   * Used to factor out inquiry functionality as it is used in more than one spot.
78   * 
79   * @author <a href="mailto:jfaath@apache.org">Jeff Faath</a>
80   */
81  public class InquiryHelper {
82  
83  	private static Log logger = LogFactory.getLog(InquiryHelper.class);
84  	
85  	public static List<Object> findBinding(FindBinding body, FindQualifiers findQualifiers, EntityManager em) throws DispositionReportFaultMessage {
86  
87  		List<Object> keysFound = new LinkedList<Object>();
88                  if (body.getServiceKey()!=null && body.getServiceKey().length() > 0) {
89                      keysFound = findBindingsByServiceKey(em, body.getServiceKey(), keysFound);
90                  }
91  		
92  		if (body.getTModelBag() == null)
93  			body.setTModelBag(new TModelBag());
94                  // First perform the embedded FindTModel search which will augment the tModel bag with any resulting tModel keys.
95  		doFindTModelEmbeddedSearch(em, body.getFindQualifiers(), body.getFindTModel(), body.getTModelBag());
96  		keysFound = FindBindingByTModelKeyQuery.select(em, findQualifiers, body.getTModelBag(), body.getServiceKey(), keysFound);
97  		keysFound = FindBindingByCategoryQuery.select(em, findQualifiers, body.getCategoryBag(), body.getServiceKey(), keysFound);
98  		keysFound = FindBindingByCategoryGroupQuery.select(em, findQualifiers, body.getCategoryBag(), body.getServiceKey(), keysFound);
99  		
100 		return keysFound;
101 	}
102 	
103 	public static BindingDetail getBindingDetailFromKeys(FindBinding body, FindQualifiers findQualifiers, EntityManager em, List<?> keysFound) throws DispositionReportFaultMessage {
104 		return getBindingDetailFromKeys(body, findQualifiers, em, keysFound, null, null, null, null);
105 	}
106 	
107 	public static BindingDetail getBindingDetailFromKeys(FindBinding body, FindQualifiers findQualifiers, EntityManager em, List<?> keysFound,
108 														 Date modifiedAfter, Date modifiedBefore, Holder<Integer> subscriptionStartIndex, Integer subscriptionMaxRows)
109 				   throws DispositionReportFaultMessage {
110 
111 		BindingDetail result = new BindingDetail();
112 		ListDescription listDesc = new ListDescription();
113 		result.setListDescription(listDesc);
114 		
115 		// Sort and retrieve the final results with paging taken into account
116 		List<?> queryResults = FetchBindingTemplatesQuery.select(em, findQualifiers, keysFound, body.getMaxRows(), body.getListHead(), listDesc);
117 
118 		// Set the currentIndex to 0 or the value of the subscriptionStartIndex
119 		int currentIndex = 0;
120 		if (subscriptionStartIndex != null && subscriptionStartIndex.value != null)
121 			currentIndex = subscriptionStartIndex.value;
122 
123 		int returnedRowCount = 0;
124 		
125 		while (currentIndex < queryResults.size()) {
126 			Object item = queryResults.get(currentIndex);
127 
128 			org.apache.juddi.model.BindingTemplate modelBindingTemplate = (org.apache.juddi.model.BindingTemplate)item;
129 			org.uddi.api_v3.BindingTemplate apiBindingTemplate = new org.uddi.api_v3.BindingTemplate();
130 			
131 			if (modifiedAfter != null && modifiedAfter.after(modelBindingTemplate.getModifiedIncludingChildren())) {
132 				currentIndex++;
133 				continue;
134 			}
135 			
136 			if (modifiedBefore != null && modifiedBefore.before(modelBindingTemplate.getModifiedIncludingChildren())) {
137 				currentIndex++;
138 				continue;
139 			}
140 			
141 			MappingModelToApi.mapBindingTemplate(modelBindingTemplate, apiBindingTemplate);
142 			
143 			result.getBindingTemplate().add(apiBindingTemplate);
144 
145 			returnedRowCount++;
146 			// If the returned rows equals the max allowed, we can end the loop (applies to subscription calls only)
147 			if (subscriptionMaxRows != null) {
148 				if (returnedRowCount == subscriptionMaxRows)
149 					break;
150 			}
151 
152 			currentIndex++;
153 		}
154 
155 		// If the loop was broken prematurely (max row count hit) we set the subscriptionStartIndex to the next index to start with.
156 		// Otherwise, set it to null so the subscription call won't trigger chunk token generation. 
157 		if (currentIndex < (queryResults.size() - 1)) {
158 			if (subscriptionStartIndex != null)
159 				subscriptionStartIndex.value = currentIndex + 1;
160 			result.setTruncated(Boolean.TRUE);
161 		}
162 		else {
163 			if (subscriptionStartIndex != null)
164 				subscriptionStartIndex.value = null;
165 			result.setTruncated(Boolean.FALSE);
166 		}
167 		result.getListDescription().setListHead(currentIndex);
168                 result.getListDescription().setActualCount(result.getBindingTemplate().size());
169                 result.getListDescription().setIncludeCount(returnedRowCount);
170 		return result;
171 	}	
172 	
173 	public static List<Object> findBusiness(FindBusiness body, FindQualifiers findQualifiers, EntityManager em) throws DispositionReportFaultMessage {
174 
175 		List<Object> keysFound = null;
176 
177 		// First perform the embedded FindTModel search which will augment the tModel bag with any resulting tModel keys.
178 		if (body.getTModelBag() == null)
179 			body.setTModelBag(new TModelBag());
180 		doFindTModelEmbeddedSearch(em, body.getFindQualifiers(), body.getFindTModel(), body.getTModelBag());
181 		
182 		// The embedded find_relatedBusinesses search is performed first.  This is done the same as the actual API call, except the resulting business keys are 
183 		// extracted and placed in the keysFound array to restrict future searches to only those keys.
184 		if (body.getFindRelatedBusinesses() != null) {
185 			FindRelatedBusinesses frb = body.getFindRelatedBusinesses();
186 			
187 			org.uddi.api_v3.RelatedBusinessInfos relatedBusinessInfos = new org.uddi.api_v3.RelatedBusinessInfos();
188 			if (body.getFindRelatedBusinesses().getBusinessKey() != null ) {
189 				getRelatedBusinesses(em, Direction.FROM_KEY, frb.getBusinessKey(), frb.getKeyedReference(), relatedBusinessInfos);
190 				getRelatedBusinesses(em, Direction.TO_KEY, frb.getBusinessKey(), frb.getKeyedReference(), relatedBusinessInfos);
191 			}
192 			else if (body.getFindRelatedBusinesses().getFromKey() != null)
193 				getRelatedBusinesses(em, Direction.FROM_KEY, frb.getFromKey(), frb.getKeyedReference(), relatedBusinessInfos);
194 			else if (body.getFindRelatedBusinesses().getToKey() != null)
195 				getRelatedBusinesses(em, Direction.TO_KEY, frb.getToKey(), frb.getKeyedReference(), relatedBusinessInfos);
196 			
197 			List<Object> relatedBusinessKeys = new ArrayList<Object>(0);
198 			for (org.uddi.api_v3.RelatedBusinessInfo rbi : relatedBusinessInfos.getRelatedBusinessInfo())
199 				relatedBusinessKeys.add(rbi.getBusinessKey());
200 			
201 			keysFound = relatedBusinessKeys;
202 		}
203 		
204 		keysFound = FindBusinessByTModelKeyQuery.select(em, findQualifiers, body.getTModelBag(), keysFound);
205 		keysFound = FindBusinessByIdentifierQuery.select(em, findQualifiers, body.getIdentifierBag(), keysFound);
206 		keysFound = FindBusinessByDiscoveryURLQuery.select(em, findQualifiers, body.getDiscoveryURLs(), keysFound);
207         if (findQualifiers.isCombineCategoryBags()) {
208             keysFound = FindBusinessByCombinedCategoryQuery.select(em, findQualifiers, body.getCategoryBag(), keysFound);
209         } else {
210             keysFound = FindBusinessByCategoryQuery.select(em, findQualifiers, body.getCategoryBag(), keysFound);
211         }
212 
213 		keysFound = FindBusinessByCategoryGroupQuery.select(em, findQualifiers, body.getCategoryBag(), keysFound);
214 		keysFound = FindBusinessByNameQuery.select(em, findQualifiers, body.getName(), keysFound);
215 		
216 		// If there no keys in the bag then remove the empty TModelBag
217 		if (body.getTModelBag().getTModelKey().size()==0) body.setTModelBag(null);
218 				
219 		return keysFound;
220 	}
221 
222 	public static BusinessList getBusinessListFromKeys(FindBusiness body, FindQualifiers findQualifiers, EntityManager em, List<?> keysFound) throws DispositionReportFaultMessage {
223 		return getBusinessListFromKeys(body, findQualifiers, em, keysFound, null, null, null, null);
224 	}
225 	
226 	public static BusinessList getBusinessListFromKeys(FindBusiness body, FindQualifiers findQualifiers, EntityManager em, List<?> keysFound,
227 													   Date modifiedAfter, Date modifiedBefore, Holder<Integer> subscriptionStartIndex, Integer subscriptionMaxRows)
228 				   throws DispositionReportFaultMessage {
229 
230 		BusinessList result = new BusinessList();
231 		ListDescription listDesc = new ListDescription();
232 		result.setListDescription(listDesc);
233 
234 		// Sort and retrieve the final results taking paging into account
235 		List<?> queryResults = FetchBusinessEntitiesQuery.select(em, findQualifiers, keysFound, body.getMaxRows(), body.getListHead(), listDesc);
236                 
237                 boolean enabled = true;
238                 try {
239                         //AppConfig.reloadConfig();
240                        enabled= AppConfig.getConfiguration().getBoolean(Property.JUDDI_ENABLE_FIND_BUSINESS_TMODEL_BAG_FILTERING, true);
241                 } catch (ConfigurationException ex) {
242                         logger.error(ex);
243                 }
244                 if (enabled) {
245                         logger.info("FindBusiness by tModelBag is enabled! Loaded from " + AppConfig.getConfigFileURL());
246                         List<?> serviceResults = null;
247                         for (int i = 0; i < queryResults.size(); i++) {
248                                 org.apache.juddi.model.BusinessEntity be = (org.apache.juddi.model.BusinessEntity) queryResults.get(i);
249 
250                                 List<Object> keysIn = new ArrayList<Object>();
251                                 List<org.apache.juddi.model.BusinessService> services = be.getBusinessServices();
252                                 for (int j = 0; j < services.size(); j++) {
253                                         keysIn.add(services.get(j).getEntityKey());
254                                 }
255 
256                                 serviceResults = FindServiceByTModelKeyQuery.select(em, findQualifiers, body.getTModelBag(), null, keysIn);
257                                 if (serviceResults == null) {
258                                         be.setBusinessServices(null);
259                                 } else {
260                                         ListDescription ldesc = new ListDescription();
261                                         result.setListDescription(listDesc);
262                                         List<?> srvcs = FetchBusinessServicesQuery.select(em, findQualifiers, serviceResults, body.getMaxRows(),
263                                                 body.getListHead(), ldesc);
264                                         be.setBusinessServices((List<org.apache.juddi.model.BusinessService>) srvcs);
265                                 }
266                         }
267                 }
268                 
269                 
270 		if (queryResults != null && queryResults.size() > 0)
271 			result.setBusinessInfos(new org.uddi.api_v3.BusinessInfos());
272 		
273 		// Set the currentIndex to 0 or the value of the subscriptionStartIndex
274 		int currentIndex = 0;
275 		if (subscriptionStartIndex != null && subscriptionStartIndex.value != null)
276 			currentIndex = subscriptionStartIndex.value;
277 
278 		int returnedRowCount = 0;
279 		
280 		while (queryResults!=null && currentIndex < queryResults.size()) {
281 			Object item = queryResults.get(currentIndex);
282 
283 			org.apache.juddi.model.BusinessEntity modelBusinessEntity = (org.apache.juddi.model.BusinessEntity)item;
284 			org.uddi.api_v3.BusinessInfo apiBusinessInfo = new org.uddi.api_v3.BusinessInfo();
285 			
286 			if (modifiedAfter != null && modifiedAfter.after(modelBusinessEntity.getModifiedIncludingChildren())){
287 				currentIndex++;
288 				continue;
289 			}
290 			
291 			if (modifiedBefore != null && modifiedBefore.before(modelBusinessEntity.getModifiedIncludingChildren())) {
292 				currentIndex++;
293 				continue;
294 			}
295 			
296 			MappingModelToApi.mapBusinessInfo(modelBusinessEntity, apiBusinessInfo);
297 			
298 			result.getBusinessInfos().getBusinessInfo().add(apiBusinessInfo);
299 
300 			returnedRowCount++;
301 			// If the returned rows equals the max allowed, we can end the loop (applies to subscription calls only)
302 			if (subscriptionMaxRows != null) {
303 				if (returnedRowCount == subscriptionMaxRows)
304 					break;
305 			}
306 
307 			currentIndex++;
308 		}
309 
310 		// If the loop was broken prematurely (max row count hit) we set the subscriptionStartIndex to the next index to start with.
311 		// Otherwise, set it to null so the subscription call won't trigger chunk token generation. 
312 		if (queryResults!=null && currentIndex < (queryResults.size() - 1)) {
313 			if (subscriptionStartIndex != null)
314 				subscriptionStartIndex.value = currentIndex + 1;
315 			result.setTruncated(Boolean.TRUE);
316 		}
317 		else {
318 			if (subscriptionStartIndex != null)
319 				subscriptionStartIndex.value = null;
320 			result.setTruncated(Boolean.FALSE);
321 		}
322 		return result;
323 	}
324 	
325 	public static List<?> findService(FindService body, FindQualifiers findQualifiers, EntityManager em) throws DispositionReportFaultMessage {
326 
327 		List<Object> keysFound = null;
328 
329 		// First perform the embedded FindTModel search which will augment the tModel bag with any resulting tModel keys.
330 		if (body.getTModelBag() == null)
331 			body.setTModelBag(new TModelBag());
332 		doFindTModelEmbeddedSearch(em, body.getFindQualifiers(), body.getFindTModel(), body.getTModelBag());
333 		
334 		keysFound = FindServiceByTModelKeyQuery.select(em, findQualifiers, body.getTModelBag(), body.getBusinessKey(), keysFound);
335         if (findQualifiers.isCombineCategoryBags()) {
336 		    keysFound = FindServiceByCombinedCategoryQuery.select(em, findQualifiers, body.getCategoryBag(), body.getBusinessKey(), keysFound);
337 		} else {
338 			keysFound = FindServiceByCategoryQuery.select(em, findQualifiers, body.getCategoryBag(), body.getBusinessKey(), keysFound);
339 		}
340 		keysFound = FindServiceByCategoryGroupQuery.select(em, findQualifiers, body.getCategoryBag(), body.getBusinessKey(), keysFound);
341 		
342 		if (body.getFindTModel()==null && body.getCategoryBag()==null && 
343 				( body.getTModelBag()==null || body.getTModelBag().getTModelKey().size() == 0) 
344 				&& body.getName().size() == 0 && body.getBusinessKey() != null) {
345 			//support searching for all services for a business
346 			findQualifiers.setApproximateMatch(true);
347 			body.getName().add(new Name("%", null));
348 		}
349 		keysFound = FindServiceByNameQuery.select(em, findQualifiers, body.getName(), body.getBusinessKey(), keysFound);
350 		
351 		if (body.getTModelBag().getTModelKey().size()==0) body.setTModelBag(null);
352 		return keysFound;
353 	}
354 	
355 	public static ServiceList getServiceListFromKeys(FindService body, FindQualifiers findQualifiers, EntityManager em, List<?> keysFound) throws DispositionReportFaultMessage {
356 		return getServiceListFromKeys(body, findQualifiers, em, keysFound, null, null, null, null);
357 	}
358 
359 	public static ServiceList getServiceListFromKeys(FindService body, FindQualifiers findQualifiers, EntityManager em, List<?> keysFound,
360 													 Date modifiedAfter, Date modifiedBefore, Holder<Integer> subscriptionStartIndex, Integer subscriptionMaxRows)
361 				   throws DispositionReportFaultMessage {
362 		ServiceList result = new ServiceList();
363 		ListDescription listDesc = new ListDescription();
364 		result.setListDescription(listDesc);
365 		
366 		// Sort and retrieve the final results taking paging into account
367 		List<?> queryResults = FetchBusinessServicesQuery.select(em, findQualifiers, keysFound, body.getMaxRows(), body.getListHead(), listDesc);
368 		if (queryResults != null && queryResults.size() > 0)
369 			result.setServiceInfos(new org.uddi.api_v3.ServiceInfos());
370 
371 		// Set the currentIndex to 0 or the value of the subscriptionStartIndex
372 		int currentIndex = 0;
373 		if (subscriptionStartIndex != null && subscriptionStartIndex.value != null)
374 			currentIndex = subscriptionStartIndex.value;
375 
376 		int returnedRowCount = 0;
377 		if (logger.isDebugEnabled()) logger.debug("Period = " + modifiedAfter + " ---- " + modifiedBefore);
378 		while (queryResults!=null && currentIndex < queryResults.size()) {
379 			Object item = queryResults.get(currentIndex);
380 
381 			org.apache.juddi.model.BusinessService modelBusinessService = (org.apache.juddi.model.BusinessService)item;
382 			org.uddi.api_v3.ServiceInfo apiServiceInfo = new org.uddi.api_v3.ServiceInfo();
383 			
384 			logger.debug(modelBusinessService.getEntityKey() + " is modified " + modelBusinessService.getModifiedIncludingChildren() + " " + modelBusinessService.getModifiedIncludingChildren().getTime() );
385 			if (modifiedAfter != null && modifiedAfter.after(modelBusinessService.getModifiedIncludingChildren())) {
386 				currentIndex++;
387 				continue;
388 			}
389 			
390 			if (modifiedBefore != null && modifiedBefore.before(modelBusinessService.getModifiedIncludingChildren())) {
391 				currentIndex++;
392 				continue;
393 			}
394 			MappingModelToApi.mapServiceInfo(modelBusinessService, apiServiceInfo);
395 			
396 			result.getServiceInfos().getServiceInfo().add(apiServiceInfo);
397 
398 			returnedRowCount++;
399 			// If the returned rows equals the max allowed, we can end the loop (applies to subscription calls only)
400 			if (subscriptionMaxRows != null) {
401 				if (returnedRowCount == subscriptionMaxRows)
402 					break;
403 			}
404 
405 			currentIndex++;
406 		}
407 
408 		// If the loop was broken prematurely (max row count hit) we set the subscriptionStartIndex to the next index to start with.
409 		// Otherwise, set it to null so the subscription call won't trigger chunk token generation. 
410 		if (queryResults!=null && currentIndex < (queryResults.size() - 1)) {
411 			if (subscriptionStartIndex != null)
412 				subscriptionStartIndex.value = currentIndex + 1;
413 			result.setTruncated(Boolean.TRUE);
414 		}
415 		else {
416 			if (subscriptionStartIndex != null)
417 				subscriptionStartIndex.value = null;
418 			result.setTruncated(Boolean.FALSE);
419 		}
420 		
421 		return result;
422 	}
423 
424 	public static List<Object> findTModel(FindTModel body, FindQualifiers findQualifiers, EntityManager em) throws DispositionReportFaultMessage {
425 		List<Object> keysFound = null;
426 
427 		keysFound = FindTModelByIdentifierQuery.select(em, findQualifiers, body.getIdentifierBag(), keysFound);
428 		keysFound = FindTModelByCategoryQuery.select(em, findQualifiers, body.getCategoryBag(), keysFound);
429 		keysFound = FindTModelByCategoryGroupQuery.select(em, findQualifiers, body.getCategoryBag(), keysFound);
430 		keysFound = FindTModelByNameQuery.select(em, findQualifiers, body.getName(), keysFound);
431 		
432 		return keysFound;
433 	}
434 
435 	public static TModelList getTModelListFromKeys(FindTModel body, FindQualifiers findQualifiers, EntityManager em, List<?> keysFound) throws DispositionReportFaultMessage {
436 		return getTModelListFromKeys(body, findQualifiers, em, keysFound, null, null, null, null);
437 	}
438 	
439 	public static TModelList getTModelListFromKeys(FindTModel body, FindQualifiers findQualifiers, EntityManager em, List<?> keysFound,
440 												   Date modifiedAfter, Date modifiedBefore, Holder<Integer> subscriptionStartIndex, Integer subscriptionMaxRows)
441 				   throws DispositionReportFaultMessage {
442 		TModelList result = new TModelList();
443 		ListDescription listDesc = new ListDescription();
444 		result.setListDescription(listDesc);
445 
446 		// Sort and retrieve the final results taking paging into account
447 		List<?> queryResults = FetchTModelsQuery.select(em, findQualifiers, keysFound, body.getMaxRows(), body.getListHead(), listDesc);
448 		if (queryResults != null && queryResults.size() > 0)
449 			result.setTModelInfos(new org.uddi.api_v3.TModelInfos());
450 		
451 		// Set the currentIndex to 0 or the value of the subscriptionStartIndex
452 		int currentIndex = 0;
453 		if (subscriptionStartIndex != null && subscriptionStartIndex.value != null)
454 			currentIndex = subscriptionStartIndex.value;
455 
456 		int returnedRowCount = 0;
457 		
458 		while (queryResults!=null && currentIndex < queryResults.size()) {
459 			Object item = queryResults.get(currentIndex);
460 			
461 			org.apache.juddi.model.Tmodel modelTModel = (org.apache.juddi.model.Tmodel)item;
462 			org.uddi.api_v3.TModelInfo apiTModelInfo = new org.uddi.api_v3.TModelInfo();
463 			
464 			if (modifiedAfter != null && modifiedAfter.after(modelTModel.getModifiedIncludingChildren())) {
465 				currentIndex++;
466 				continue;
467 			}
468 			
469 			if (modifiedBefore != null && modifiedBefore.before(modelTModel.getModifiedIncludingChildren())) {
470 				currentIndex++;
471 				continue;
472 			}
473 			
474 			MappingModelToApi.mapTModelInfo(modelTModel, apiTModelInfo);
475 			
476 			result.getTModelInfos().getTModelInfo().add(apiTModelInfo);
477 			
478 			returnedRowCount++;
479 			// If the returned rows equals the max allowed, we can end the loop (applies to subscription calls only)
480 			if (subscriptionMaxRows != null) {
481 				if (returnedRowCount == subscriptionMaxRows)
482 					break;
483 			}
484 			
485 			currentIndex++;
486 		}
487 		
488 		// If the loop was broken prematurely (max row count hit) we set the subscriptionStartIndex to the next index to start with.
489 		// Otherwise, set it to null so the subscription call won't trigger chunk token generation. 
490 		if (queryResults!=null && currentIndex < (queryResults.size() - 1)) {
491 			if (subscriptionStartIndex != null)
492 				subscriptionStartIndex.value = currentIndex + 1;
493 			result.setTruncated(Boolean.TRUE);
494 		}
495 		else {
496 			if (subscriptionStartIndex != null)
497 				subscriptionStartIndex.value = null;
498 			result.setTruncated(Boolean.FALSE);
499 		}
500 		
501 		return result;
502 	}
503 	
504 	
505 	/*
506 	 * Retrieves related businesses based on the focal business and the direction (fromKey or toKey).  The focal business is retrieved and then the
507 	 * appropriate publisher assertion collection is examined for matches.  The assertion must be "completed" and if a keyedReference is passed, it must
508 	 * match exactly.  Successful assertion matches are mapped to a RelationBusinessInfo structure and added to the passed in RelationalBusinessInfos 
509 	 * structure.
510 	 */
511 	public static void getRelatedBusinesses(EntityManager em, 
512 											Direction direction, 
513 											String focalKey, 
514 											org.uddi.api_v3.KeyedReference keyedRef,
515 											org.uddi.api_v3.RelatedBusinessInfos relatedBusinessInfos)
516 			throws DispositionReportFaultMessage {
517 		getRelatedBusinesses(em, direction, focalKey, keyedRef, relatedBusinessInfos, null, null);
518 	}
519 	
520 	public static void getRelatedBusinesses(EntityManager em, 
521 											Direction direction, 
522 											String focalKey, 
523 											org.uddi.api_v3.KeyedReference keyedRef,
524 											org.uddi.api_v3.RelatedBusinessInfos relatedBusinessInfos,
525 											Date modifiedAfter,
526 											Date modifiedBefore)
527 			throws DispositionReportFaultMessage {
528 		if (relatedBusinessInfos == null)
529 			relatedBusinessInfos = new org.uddi.api_v3.RelatedBusinessInfos();
530 		org.apache.juddi.model.BusinessEntity focalBusiness = null;
531 		try {
532 			focalBusiness = em.find(org.apache.juddi.model.BusinessEntity.class, focalKey);
533 		} catch (ClassCastException e) {}
534 		if (focalBusiness == null)
535 			throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.BusinessNotFound", focalKey));
536 
537 		List<org.apache.juddi.model.PublisherAssertion> pubAssertList = null;
538 		if (direction == Direction.FROM_KEY)
539 			pubAssertList = focalBusiness.getPublisherAssertionsForFromKey();
540 		else
541 			pubAssertList = focalBusiness.getPublisherAssertionsForToKey();
542 		
543 		if (pubAssertList != null) {
544 			for (org.apache.juddi.model.PublisherAssertion modelPublisherAssertion : pubAssertList) {
545 				if ("true".equalsIgnoreCase(modelPublisherAssertion.getFromCheck()) && "true".equalsIgnoreCase(modelPublisherAssertion.getToCheck())) {
546 					if (keyedRef != null) {
547 						if(!keyedRef.getTModelKey().equals(modelPublisherAssertion.getTmodelKey()) || 
548 						   !keyedRef.getKeyName().equals(modelPublisherAssertion.getKeyName()) || 
549 						   !keyedRef.getKeyValue().equals(modelPublisherAssertion.getKeyValue())) {
550 							continue;
551 						}
552 					}
553 					
554 					org.apache.juddi.model.BusinessEntity modelRelatedBusiness  = null;
555 					if (direction == Direction.FROM_KEY)
556 						modelRelatedBusiness = em.find(org.apache.juddi.model.BusinessEntity.class, modelPublisherAssertion.getId().getToKey());
557 					else
558 						modelRelatedBusiness = em.find(org.apache.juddi.model.BusinessEntity.class, modelPublisherAssertion.getId().getFromKey());
559 					
560 					if (modifiedAfter != null && modifiedAfter.after(modelRelatedBusiness.getModifiedIncludingChildren()))
561 						continue;
562 					
563 					if (modifiedBefore != null && modifiedBefore.before(modelRelatedBusiness.getModifiedIncludingChildren()))
564 						continue;
565 					
566 					org.uddi.api_v3.RelatedBusinessInfo apiRelatedBusinessInfo = new org.uddi.api_v3.RelatedBusinessInfo();
567 
568 					MappingModelToApi.mapRelatedBusinessInfo(modelPublisherAssertion, modelRelatedBusiness, direction, apiRelatedBusinessInfo);
569 					
570 					relatedBusinessInfos.getRelatedBusinessInfo().add(apiRelatedBusinessInfo);
571 				}
572 			}
573 		}
574 		
575 	}
576 
577 	public static RelatedBusinessesList getRelatedBusinessesList(FindRelatedBusinesses body, EntityManager em) throws DispositionReportFaultMessage {
578 		return getRelatedBusinessesList(body, em, null, null);
579 	}
580 	
581 	public static RelatedBusinessesList getRelatedBusinessesList(FindRelatedBusinesses body, EntityManager em, Date modifiedAfter, Date modifiedBefore) throws DispositionReportFaultMessage {
582 		RelatedBusinessesList result = new RelatedBusinessesList();
583 		result.setBusinessKey(body.getBusinessKey());
584 		ListDescription listDesc = new ListDescription();
585 		result.setListDescription(listDesc);
586 		
587 		// Either one of the businessKey, fromKey or toKey will be passed.  This is considered the "focal" business to which related businesses must be
588 		// found.  Rather than use a query, it seems simpler to take advantage of the model's publisher assertion collections.
589 		org.uddi.api_v3.RelatedBusinessInfos relatedBusinessInfos = new org.uddi.api_v3.RelatedBusinessInfos();
590 		if (body.getBusinessKey() != null ) {
591 			InquiryHelper.getRelatedBusinesses(em, Direction.FROM_KEY, body.getBusinessKey(), body.getKeyedReference(), relatedBusinessInfos, modifiedAfter, modifiedBefore);
592 			InquiryHelper.getRelatedBusinesses(em, Direction.TO_KEY, body.getBusinessKey(), body.getKeyedReference(), relatedBusinessInfos, modifiedAfter, modifiedBefore);
593 		}
594 		else if (body.getFromKey() != null) {
595 			InquiryHelper.getRelatedBusinesses(em, Direction.FROM_KEY, body.getFromKey(), body.getKeyedReference(), relatedBusinessInfos, modifiedAfter, modifiedBefore);
596 		    result.setBusinessKey(body.getFromKey());
597 		} else if (body.getToKey() != null) {
598 			InquiryHelper.getRelatedBusinesses(em, Direction.TO_KEY, body.getToKey(), body.getKeyedReference(), relatedBusinessInfos, modifiedAfter, modifiedBefore);
599             result.setBusinessKey(body.getToKey());
600 		}
601 		if (relatedBusinessInfos.getRelatedBusinessInfo().size() > 0) {
602 			// TODO: Do proper pagination!
603 			listDesc.setActualCount(relatedBusinessInfos.getRelatedBusinessInfo().size());
604 			listDesc.setIncludeCount(relatedBusinessInfos.getRelatedBusinessInfo().size());
605 			listDesc.setListHead(1);
606 			
607 			result.setRelatedBusinessInfos(relatedBusinessInfos);
608 		}
609 		
610 		return result;
611 	}
612 		
613 	/**
614 	 * Performs the necessary queries for the find_tModel search and adds resulting tModel keys to the tModelBag provided.
615 	 */
616 	private static void doFindTModelEmbeddedSearch(EntityManager em, 
617 											org.uddi.api_v3.FindQualifiers fq, 
618 											FindTModel findTmodel, 
619 											TModelBag tmodelBag)
620 			throws DispositionReportFaultMessage {
621 
622 		
623 		if (findTmodel != null && tmodelBag != null) {
624 			org.apache.juddi.query.util.FindQualifiers findQualifiers = new org.apache.juddi.query.util.FindQualifiers();
625 			findQualifiers.mapApiFindQualifiers(findTmodel.getFindQualifiers());
626 
627 			
628 			List<Object> tmodelKeysFound = null;
629 			tmodelKeysFound = FindTModelByIdentifierQuery.select(em, findQualifiers, findTmodel.getIdentifierBag(), tmodelKeysFound);
630 			tmodelKeysFound = FindTModelByCategoryQuery.select(em, findQualifiers, findTmodel.getCategoryBag(), tmodelKeysFound);
631 			tmodelKeysFound = FindTModelByCategoryGroupQuery.select(em, findQualifiers, findTmodel.getCategoryBag(), tmodelKeysFound);
632 			tmodelKeysFound = FindTModelByNameQuery.select(em, findQualifiers, findTmodel.getName(), tmodelKeysFound);
633 			
634 			if (tmodelKeysFound != null && tmodelKeysFound.size() > 0) {
635 				for (Object item : tmodelKeysFound)
636 					tmodelBag.getTModelKey().add((String)item);
637 			}
638 		}
639 	}
640 
641     private static List<Object> findBindingsByServiceKey(EntityManager em, String serviceKey, List<Object> keysFound) {
642         org.apache.juddi.model.BusinessService modelBusinessService=em.find(org.apache.juddi.model.BusinessService.class, serviceKey);
643         for (BindingTemplate bt : modelBusinessService.getBindingTemplates()){
644             keysFound.add(bt.getEntityKey());
645         }
646         return keysFound;
647     }
648 	
649 	
650 }