View Javadoc

1   /**
2    * Copyright 2010 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   */
15  
16  package org.kuali.student.lum.lu.service.impl;
17  
18  import java.util.ArrayList;
19  import java.util.Date;
20  import java.util.HashMap;
21  import java.util.HashSet;
22  import java.util.Iterator;
23  import java.util.List;
24  import java.util.Map;
25  import java.util.Map.Entry;
26  import java.util.Set;
27  
28  import javax.jws.WebService;
29  import javax.persistence.NoResultException;
30  
31  import org.apache.log4j.Logger;
32  import org.kuali.student.common.dictionary.dto.ObjectStructureDefinition;
33  import org.kuali.student.common.dictionary.service.DictionaryService;
34  import org.kuali.student.common.dto.CurrencyAmountInfo;
35  import org.kuali.student.common.dto.DtoConstants;
36  import org.kuali.student.common.dto.StatusInfo;
37  import org.kuali.student.common.entity.Amount;
38  import org.kuali.student.common.entity.TimeAmount;
39  import org.kuali.student.common.entity.Version;
40  import org.kuali.student.common.entity.VersionEntity;
41  import org.kuali.student.common.exceptions.AlreadyExistsException;
42  import org.kuali.student.common.exceptions.CircularRelationshipException;
43  import org.kuali.student.common.exceptions.DataValidationErrorException;
44  import org.kuali.student.common.exceptions.DependentObjectsExistException;
45  import org.kuali.student.common.exceptions.DoesNotExistException;
46  import org.kuali.student.common.exceptions.IllegalVersionSequencingException;
47  import org.kuali.student.common.exceptions.InvalidParameterException;
48  import org.kuali.student.common.exceptions.MissingParameterException;
49  import org.kuali.student.common.exceptions.OperationFailedException;
50  import org.kuali.student.common.exceptions.PermissionDeniedException;
51  import org.kuali.student.common.exceptions.UnsupportedActionException;
52  import org.kuali.student.common.exceptions.VersionMismatchException;
53  import org.kuali.student.common.search.dto.SearchCriteriaTypeInfo;
54  import org.kuali.student.common.search.dto.SearchRequest;
55  import org.kuali.student.common.search.dto.SearchResult;
56  import org.kuali.student.common.search.dto.SearchResultCell;
57  import org.kuali.student.common.search.dto.SearchResultRow;
58  import org.kuali.student.common.search.dto.SearchResultTypeInfo;
59  import org.kuali.student.common.search.dto.SearchTypeInfo;
60  import org.kuali.student.common.search.service.SearchManager;
61  import org.kuali.student.common.validation.dto.ValidationResultInfo;
62  import org.kuali.student.common.validator.Validator;
63  import org.kuali.student.common.validator.ValidatorFactory;
64  import org.kuali.student.common.versionmanagement.dto.VersionDisplayInfo;
65  import org.kuali.student.lum.lu.LUConstants;
66  import org.kuali.student.lum.lu.dao.LuDao;
67  import org.kuali.student.lum.lu.dto.AccreditationInfo;
68  import org.kuali.student.lum.lu.dto.AdminOrgInfo;
69  import org.kuali.student.lum.lu.dto.AffiliatedOrgInfo;
70  import org.kuali.student.lum.lu.dto.CluCluRelationInfo;
71  import org.kuali.student.lum.lu.dto.CluFeeRecordInfo;
72  import org.kuali.student.lum.lu.dto.CluIdentifierInfo;
73  import org.kuali.student.lum.lu.dto.CluInfo;
74  import org.kuali.student.lum.lu.dto.CluInstructorInfo;
75  import org.kuali.student.lum.lu.dto.CluLoRelationInfo;
76  import org.kuali.student.lum.lu.dto.CluLoRelationTypeInfo;
77  import org.kuali.student.lum.lu.dto.CluPublicationInfo;
78  import org.kuali.student.lum.lu.dto.CluResultInfo;
79  import org.kuali.student.lum.lu.dto.CluResultTypeInfo;
80  import org.kuali.student.lum.lu.dto.CluSetInfo;
81  import org.kuali.student.lum.lu.dto.CluSetTreeViewInfo;
82  import org.kuali.student.lum.lu.dto.CluSetTypeInfo;
83  import org.kuali.student.lum.lu.dto.DeliveryMethodTypeInfo;
84  import org.kuali.student.lum.lu.dto.FieldInfo;
85  import org.kuali.student.lum.lu.dto.InstructionalFormatTypeInfo;
86  import org.kuali.student.lum.lu.dto.LuCodeInfo;
87  import org.kuali.student.lum.lu.dto.LuCodeTypeInfo;
88  import org.kuali.student.lum.lu.dto.LuLuRelationTypeInfo;
89  import org.kuali.student.lum.lu.dto.LuPublicationTypeInfo;
90  import org.kuali.student.lum.lu.dto.LuTypeInfo;
91  import org.kuali.student.lum.lu.dto.LuiInfo;
92  import org.kuali.student.lum.lu.dto.LuiLuiRelationInfo;
93  import org.kuali.student.lum.lu.dto.MembershipQueryInfo;
94  import org.kuali.student.lum.lu.dto.ResultOptionInfo;
95  import org.kuali.student.lum.lu.dto.ResultUsageTypeInfo;
96  import org.kuali.student.lum.lu.entity.Clu;
97  import org.kuali.student.lum.lu.entity.CluAccounting;
98  import org.kuali.student.lum.lu.entity.CluAccountingAttribute;
99  import org.kuali.student.lum.lu.entity.CluAccreditation;
100 import org.kuali.student.lum.lu.entity.CluAccreditationAttribute;
101 import org.kuali.student.lum.lu.entity.CluAdminOrg;
102 import org.kuali.student.lum.lu.entity.CluAdminOrgAttribute;
103 import org.kuali.student.lum.lu.entity.CluAtpTypeKey;
104 import org.kuali.student.lum.lu.entity.CluAttribute;
105 import org.kuali.student.lum.lu.entity.CluCampusLocation;
106 import org.kuali.student.lum.lu.entity.CluCluRelation;
107 import org.kuali.student.lum.lu.entity.CluCluRelationAttribute;
108 import org.kuali.student.lum.lu.entity.CluFee;
109 import org.kuali.student.lum.lu.entity.CluIdentifier;
110 import org.kuali.student.lum.lu.entity.CluInstructor;
111 import org.kuali.student.lum.lu.entity.CluInstructorAttribute;
112 import org.kuali.student.lum.lu.entity.CluLoRelation;
113 import org.kuali.student.lum.lu.entity.CluLoRelationAttribute;
114 import org.kuali.student.lum.lu.entity.CluLoRelationType;
115 import org.kuali.student.lum.lu.entity.CluPublication;
116 import org.kuali.student.lum.lu.entity.CluPublicationAttribute;
117 import org.kuali.student.lum.lu.entity.CluPublicationType;
118 import org.kuali.student.lum.lu.entity.CluPublicationVariant;
119 import org.kuali.student.lum.lu.entity.CluResult;
120 import org.kuali.student.lum.lu.entity.CluResultType;
121 import org.kuali.student.lum.lu.entity.CluSet;
122 import org.kuali.student.lum.lu.entity.CluSetAttribute;
123 import org.kuali.student.lum.lu.entity.CluSetJoinVersionIndClu;
124 import org.kuali.student.lum.lu.entity.CluSetType;
125 import org.kuali.student.lum.lu.entity.DeliveryMethodType;
126 import org.kuali.student.lum.lu.entity.InstructionalFormatType;
127 import org.kuali.student.lum.lu.entity.LuCode;
128 import org.kuali.student.lum.lu.entity.LuCodeAttribute;
129 import org.kuali.student.lum.lu.entity.LuCodeType;
130 import org.kuali.student.lum.lu.entity.LuLuRelationType;
131 import org.kuali.student.lum.lu.entity.LuPublicationType;
132 import org.kuali.student.lum.lu.entity.LuRichText;
133 import org.kuali.student.lum.lu.entity.LuType;
134 import org.kuali.student.lum.lu.entity.Lui;
135 import org.kuali.student.lum.lu.entity.LuiAttribute;
136 import org.kuali.student.lum.lu.entity.LuiLuiRelation;
137 import org.kuali.student.lum.lu.entity.LuiLuiRelationAttribute;
138 import org.kuali.student.lum.lu.entity.MembershipQuery;
139 import org.kuali.student.lum.lu.entity.ResultOption;
140 import org.kuali.student.lum.lu.entity.ResultUsageType;
141 import org.kuali.student.lum.lu.service.LuService;
142 import org.kuali.student.lum.lu.service.LuServiceConstants;
143 import org.springframework.beans.BeanUtils;
144 import org.springframework.transaction.annotation.Transactional;
145 
146 import edu.emory.mathcs.backport.java.util.Collections;
147 
148 
149 @WebService(endpointInterface = "org.kuali.student.lum.lu.service.LuService", serviceName = "LuService", portName = "LuService", targetNamespace = "http://student.kuali.org/wsdl/lu")
150 @Transactional(readOnly=true,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
151 public class LuServiceImpl implements LuService {
152 
153 	final Logger logger = Logger.getLogger(LuServiceImpl.class);
154 
155 	private LuDao luDao;
156 	private SearchManager searchManager;
157 	private DictionaryService dictionaryServiceDelegate;
158 	private ValidatorFactory validatorFactory;
159 
160 	public void setSearchManager(SearchManager searchManager) {
161 		this.searchManager = searchManager;
162 	}
163 
164 	public void setDictionaryServiceDelegate(
165 			DictionaryService dictionaryServiceDelegate) {
166 		this.dictionaryServiceDelegate = dictionaryServiceDelegate;
167 	}
168 
169 	public DictionaryService getDictionaryServiceDelegate() {
170 		return dictionaryServiceDelegate;
171 	}
172 
173 
174 	/**************************************************************************
175 	 * SETUP OPERATION *
176 	 **************************************************************************/
177 
178 	@Override
179 	public List<DeliveryMethodTypeInfo> getDeliveryMethodTypes()
180 			throws OperationFailedException {
181 		return LuServiceAssembler.toDeliveryMethodTypeInfos(luDao
182 				.find(DeliveryMethodType.class));
183 	}
184 
185 	@Override
186 	public DeliveryMethodTypeInfo getDeliveryMethodType(
187 			String deliveryMethodTypeKey) throws DoesNotExistException,
188 			InvalidParameterException, MissingParameterException,
189 			OperationFailedException {
190 
191 		checkForMissingParameter(deliveryMethodTypeKey, "deliveryMethodTypeKey");
192 
193 		return LuServiceAssembler.toDeliveryMethodTypeInfo(luDao.fetch(
194 				DeliveryMethodType.class, deliveryMethodTypeKey));
195 	}
196 
197 	@Override
198 	public List<InstructionalFormatTypeInfo> getInstructionalFormatTypes()
199 			throws OperationFailedException {
200 		return LuServiceAssembler.toInstructionalFormatTypeInfos(luDao
201 				.find(InstructionalFormatType.class));
202 	}
203 
204 	@Override
205 	public InstructionalFormatTypeInfo getInstructionalFormatType(
206 			String instructionalFormatTypeKey) throws DoesNotExistException,
207 			InvalidParameterException, MissingParameterException,
208 			OperationFailedException {
209 		checkForMissingParameter(instructionalFormatTypeKey,
210 				"instructionalFormatTypeKey");
211 
212 		return LuServiceAssembler.toInstructionalFormatTypeInfo(luDao.fetch(
213 				InstructionalFormatType.class, instructionalFormatTypeKey));
214 	}
215 
216 	@Override
217 	public List<LuTypeInfo> getLuTypes() throws OperationFailedException {
218 		return LuServiceAssembler.toLuTypeInfos(luDao.find(LuType.class));
219 	}
220 
221 	@Override
222 	public LuTypeInfo getLuType(String luTypeKey) throws DoesNotExistException,
223 			InvalidParameterException, MissingParameterException,
224 			OperationFailedException {
225 		checkForMissingParameter(luTypeKey, "luTypeKey");
226 
227 		return LuServiceAssembler.toLuTypeInfo(luDao.fetch(LuType.class,
228 				luTypeKey));
229 	}
230 
231 	@Override
232 	public LuCodeTypeInfo getLuCodeType(String luCodeTypeKey)
233 			throws DoesNotExistException, InvalidParameterException,
234 			MissingParameterException, OperationFailedException {
235 		checkForMissingParameter(luCodeTypeKey, "luCodeTypeKey");
236 		return LuServiceAssembler.toLuCodeTypeInfo(luDao.fetch(
237 				LuCodeType.class, luCodeTypeKey));
238 	}
239 
240 	@Override
241 	public List<LuCodeTypeInfo> getLuCodeTypes()
242 			throws OperationFailedException {
243 		return LuServiceAssembler.toLuCodeTypeInfos(luDao
244 				.find(LuCodeType.class));
245 	}
246 
247 	@Override
248 	public List<LuLuRelationTypeInfo> getLuLuRelationTypes()
249 			throws OperationFailedException {
250 		return LuServiceAssembler.toLuLuRelationTypeInfos(luDao
251 				.find(LuLuRelationType.class));
252 	}
253 
254 	@Override
255 	public LuLuRelationTypeInfo getLuLuRelationType(String luLuRelationTypeKey)
256 			throws OperationFailedException, MissingParameterException,
257 			DoesNotExistException {
258 		checkForMissingParameter(luLuRelationTypeKey, "luLuRelationTypeKey");
259 
260 		LuLuRelationType luLuRelationType = luDao.fetch(LuLuRelationType.class,
261 				luLuRelationTypeKey);
262 		return LuServiceAssembler.toLuLuRelationTypeInfo(luLuRelationType);
263 	}
264 
265 	@Override
266 	public List<String> getAllowedLuLuRelationTypesForLuType(String luTypeKey,
267 			String relatedLuTypeKey) throws DoesNotExistException,
268 			InvalidParameterException, MissingParameterException,
269 			OperationFailedException {
270 		checkForMissingParameter(luTypeKey, "luTypeKey");
271 		checkForMissingParameter(relatedLuTypeKey, "relatedLuTypeKey");
272 
273 		return luDao.getAllowedLuLuRelationTypesForLuType(luTypeKey,
274 				relatedLuTypeKey);
275 	}
276 
277 	@Override
278 	public List<LuPublicationTypeInfo> getLuPublicationTypes()
279 			throws OperationFailedException {
280 		return LuServiceAssembler.toLuPublicationTypeInfos(luDao
281 				.find(LuPublicationType.class));
282 	}
283 
284 	@Override
285 	public LuPublicationTypeInfo getLuPublicationType(
286 			String luPublicationTypeKey) throws DoesNotExistException,
287 			InvalidParameterException, MissingParameterException,
288 			OperationFailedException {
289 		checkForMissingParameter(luPublicationTypeKey, "luPublicationTypeKey");
290 
291 		return LuServiceAssembler.toLuPublicationTypeInfo(luDao.fetch(
292 				LuPublicationType.class, luPublicationTypeKey));
293 	}
294 
295 	@Override
296 	public List<String> getLuPublicationTypesForLuType(String luTypeKey)
297 			throws DoesNotExistException, InvalidParameterException,
298 			MissingParameterException, OperationFailedException {
299 		throw new UnsupportedOperationException("getLuPublicationTypesForLuType");
300 	}
301 
302 	@Override
303 	public List<CluResultTypeInfo> getCluResultTypes()
304 			throws OperationFailedException {
305 		return LuServiceAssembler.toCluResultTypeInfos(luDao
306 				.find(CluResultType.class));
307 	}
308 
309 	@Override
310 	public CluResultTypeInfo getCluResultType(String cluResultTypeKey)
311 			throws DoesNotExistException, InvalidParameterException,
312 			MissingParameterException, OperationFailedException {
313 		return LuServiceAssembler.toCluResultTypeInfo(luDao.fetch(
314 				CluResultType.class, cluResultTypeKey));
315 	}
316 
317 	@Override
318 	public List<CluResultTypeInfo> getCluResultTypesForLuType(String luTypeKey)
319 			throws DoesNotExistException, InvalidParameterException,
320 			MissingParameterException, OperationFailedException {
321 		checkForMissingParameter(luTypeKey, "luTypeKey");
322 		return LuServiceAssembler.toCluResultTypeInfos((luDao
323 				.getAllowedCluResultTypesForLuType(luTypeKey)));
324 	}
325 
326 	@Override
327 	public List<ResultUsageTypeInfo> getResultUsageTypes()
328 			throws OperationFailedException {
329 		return LuServiceAssembler.toResultUsageTypeInfos(luDao
330 				.find(ResultUsageType.class));
331 	}
332 
333 	@Override
334 	public ResultUsageTypeInfo getResultUsageType(String resultUsageTypeKey)
335 			throws DoesNotExistException, InvalidParameterException,
336 			MissingParameterException, OperationFailedException {
337 		checkForMissingParameter(resultUsageTypeKey, "resultUsageTypeKey");
338 		return LuServiceAssembler.toResultUsageTypeInfo(luDao.fetch(
339 				ResultUsageType.class, resultUsageTypeKey));
340 	}
341 
342 	@Override
343 	public List<String> getAllowedResultUsageTypesForLuType(String luTypeKey)
344 			throws DoesNotExistException, InvalidParameterException,
345 			MissingParameterException, OperationFailedException {
346 		checkForMissingParameter(luTypeKey, "luTypeKey");
347 
348 		return luDao.getAllowedResultUsageTypesForLuType(luTypeKey);
349 	}
350 
351 	@Override
352 	public List<String> getAllowedResultComponentTypesForResultUsageType(
353 			String resultUsageTypeKey) throws DoesNotExistException,
354 			InvalidParameterException, MissingParameterException,
355 			OperationFailedException {
356 
357 		checkForMissingParameter(resultUsageTypeKey, "resultUsageTypeKey");
358 
359 		return luDao
360 				.getAllowedResultComponentTypesForResultUsageType(resultUsageTypeKey);
361 	}
362 
363 	@Override
364 	public CluLoRelationTypeInfo getCluLoRelationType(
365 			String cluLoRelationTypeKey) throws DoesNotExistException,
366 			InvalidParameterException, MissingParameterException,
367 			OperationFailedException {
368 		checkForMissingParameter(cluLoRelationTypeKey, "cluLoRelationTypeKey");
369 
370 		CluLoRelationType cluLoRelationType = luDao.fetch(
371 				CluLoRelationType.class, cluLoRelationTypeKey);
372 		return LuServiceAssembler.toCluLoRelationTypeInfo(cluLoRelationType);
373 	}
374 
375 	@Override
376 	public List<CluLoRelationTypeInfo> getCluLoRelationTypes()
377 			throws OperationFailedException {
378 		return LuServiceAssembler.toCluLoRelationTypeInfos(luDao
379 				.find(CluLoRelationType.class));
380 	}
381 
382 	@Override
383 	public List<String> getAllowedCluLoRelationTypesForLuType(String luTypeKey)
384 			throws DoesNotExistException, InvalidParameterException,
385 			MissingParameterException, OperationFailedException {
386 
387 		checkForMissingParameter(luTypeKey, luTypeKey);
388 
389 		return luDao.getAllowedCluLoRelationTypesForLuType(luTypeKey);
390 	}
391 
392 	@Override
393 	public List<CluSetTypeInfo> getCluSetTypes()
394 			throws OperationFailedException {
395 		return LuServiceAssembler.toCluSetTypeInfos(luDao
396 				.find(CluSetType.class));
397 	}
398 
399 	@Override
400 	public CluSetTypeInfo getCluSetType(String cluSetTypeKey)
401 			throws DoesNotExistException, InvalidParameterException,
402 			MissingParameterException, OperationFailedException {
403 		checkForMissingParameter(cluSetTypeKey, "cluSetTypeKey");
404 		return LuServiceAssembler.toCluSetTypeInfo(luDao.fetch(
405 				CluSetType.class, cluSetTypeKey));
406 	}
407 
408 	/**************************************************************************
409 	 * READ OPERATION *
410 	 **************************************************************************/
411 
412 	// **** Core **********
413 	@Override
414 	public CluInfo getClu(String cluId) throws DoesNotExistException,
415 			InvalidParameterException, MissingParameterException,
416 			OperationFailedException {
417 
418 		checkForMissingParameter(cluId, "cluId");
419 
420 		Clu clu = luDao.fetch(Clu.class, cluId);
421 		return LuServiceAssembler.toCluInfo(clu);
422 	}
423 
424 	@Override
425 	public List<CluInfo> getClusByIdList(List<String> cluIdList)
426 			throws DoesNotExistException, InvalidParameterException,
427 			MissingParameterException, OperationFailedException {
428 		checkForMissingParameter(cluIdList, "cluIdList");
429 		checkForEmptyList(cluIdList, "cluIdList");
430 		List<Clu> clus = luDao.getClusByIdList(cluIdList);
431 		return LuServiceAssembler.toCluInfos(clus);
432 	}
433 
434 	@Override
435 	public List<CluInfo> getClusByLuType(String luTypeKey, String luState)
436 			throws DoesNotExistException, InvalidParameterException,
437 			MissingParameterException, OperationFailedException {
438 		checkForMissingParameter(luTypeKey, "luTypeKey");
439 		checkForMissingParameter(luState, "lustate");
440 		List<Clu> clus = luDao.getClusByLuType(luTypeKey, luState);
441 		return LuServiceAssembler.toCluInfos(clus);
442 	}
443 
444 	@Override
445 	public List<String> getCluIdsByLuType(String luTypeKey, String luState)
446 			throws DoesNotExistException, InvalidParameterException,
447 			MissingParameterException, OperationFailedException {
448 		checkForMissingParameter(luTypeKey, "luTypeKey");
449 		checkForMissingParameter(luState, "luState");
450 		List<Clu> clus = luDao.getClusByLuType(luTypeKey, luState);
451 		List<String> ids = new ArrayList<String>(clus.size());
452 		for (Clu clu : clus) {
453 			ids.add(clu.getId());
454 		}
455 		return ids;
456 	}
457 
458 	// ****** Relations
459 
460 	@Override
461 	public List<String> getAllowedLuLuRelationTypesByCluId(String cluId,
462 			String relatedCluId) throws DoesNotExistException,
463 			InvalidParameterException, MissingParameterException,
464 			OperationFailedException {
465 		checkForMissingParameter(cluId, "cluId");
466 		checkForMissingParameter(relatedCluId, "relatedCluId");
467 
468 		return luDao.getAllowedLuLuRelationTypesByCluId(cluId, relatedCluId);
469 	}
470 
471 	@Override
472 	public List<CluInfo> getClusByRelation(String relatedCluId,
473 			String luLuRelationTypeKey) throws DoesNotExistException,
474 			InvalidParameterException, MissingParameterException,
475 			OperationFailedException {
476 		checkForMissingParameter(relatedCluId, "relatedCluId");
477 		checkForMissingParameter(luLuRelationTypeKey, "luLuRelationTypeKey");
478 
479 		List<Clu> clus = luDao.getClusByRelation(relatedCluId,
480 				luLuRelationTypeKey);
481 		List<CluInfo> result = LuServiceAssembler.toCluInfos(clus);
482 		return result;
483 
484 	}
485 
486 	@Override
487 	public List<String> getCluIdsByRelation(String relatedCluId,
488 			String luLuRelationTypeKey) throws DoesNotExistException,
489 			InvalidParameterException, MissingParameterException,
490 			OperationFailedException {
491 		checkForMissingParameter(relatedCluId, "relatedCluId");
492 		checkForMissingParameter(luLuRelationTypeKey, "luLuRelationTypeKey");
493 
494         List<String> cluIds = luDao.getCluIdsByRelatedCluId(relatedCluId, luLuRelationTypeKey);
495         return cluIds;
496 	}
497 
498 	@Override
499 	public List<CluInfo> getRelatedClusByCluId(String cluId,
500 			String luLuRelationTypeKey) throws DoesNotExistException,
501 			InvalidParameterException, MissingParameterException,
502 			OperationFailedException {
503 		checkForMissingParameter(cluId, "cluId");
504 		checkForMissingParameter(luLuRelationTypeKey, "luLuRelationTypeKey");
505 		List<Clu> relatedClus = luDao.getRelatedClusByCluId(cluId,
506 				luLuRelationTypeKey);
507 		return LuServiceAssembler.toCluInfos(relatedClus);
508 	}
509 
510 	@Override
511 	public List<String> getRelatedCluIdsByCluId(String cluId,
512 			String luLuRelationTypeKey) throws DoesNotExistException,
513 			InvalidParameterException, MissingParameterException,
514 			OperationFailedException {
515 		checkForMissingParameter(cluId, "cluId");
516 		checkForMissingParameter(luLuRelationTypeKey, "luLuRelationTypeKey");
517 		List<String> relatedCluIds = luDao.getRelatedCluIdsByCluId(cluId,
518 				luLuRelationTypeKey);
519 		return relatedCluIds;
520 	}
521 
522 	@Override
523 	public CluCluRelationInfo getCluCluRelation(String cluCluRelationId)
524 			throws DoesNotExistException, InvalidParameterException,
525 			MissingParameterException, OperationFailedException {
526 		checkForMissingParameter(cluCluRelationId, "cluCluRelationId");
527 		return LuServiceAssembler.toCluCluRelationInfo(luDao.fetch(
528 				CluCluRelation.class, cluCluRelationId));
529 	}
530 
531 	@Override
532 	public List<CluCluRelationInfo> getCluCluRelationsByClu(String cluId)
533 			throws DoesNotExistException, InvalidParameterException,
534 			MissingParameterException, OperationFailedException {
535 		checkForMissingParameter(cluId, "cluId");
536 		List<CluCluRelation> cluCluRelations = luDao
537 				.getCluCluRelationsByClu(cluId);
538 		return LuServiceAssembler.toCluCluRelationInfos(cluCluRelations);
539 	}
540 
541 	// **** Publication
542 	@Override
543 	public List<CluPublicationInfo> getCluPublicationsByCluId(String cluId)
544 			throws DoesNotExistException, InvalidParameterException,
545 			MissingParameterException, OperationFailedException {
546 	      checkForMissingParameter(cluId, "cluId");
547 	      List<CluPublication> cluPublications = luDao.getCluPublicationsByCluId(cluId);
548 	      return LuServiceAssembler.toCluPublicationInfos(cluPublications);
549 	}
550 
551 	@Override
552 	public List<CluPublicationInfo> getCluPublicationsByType(
553 			String luPublicationTypeKey) throws DoesNotExistException,
554 			InvalidParameterException, MissingParameterException,
555 			OperationFailedException {
556 	      checkForMissingParameter(luPublicationTypeKey, "luPublicationTypeKey");
557 	      List<CluPublication> cluPublications = luDao.getCluPublicationsByType(luPublicationTypeKey);
558 	      return LuServiceAssembler.toCluPublicationInfos(cluPublications);
559 	}
560 
561 	@Override
562 	public CluPublicationInfo getCluPublication(String cluPublicationId)
563 			throws DoesNotExistException, InvalidParameterException,
564 			MissingParameterException, OperationFailedException {
565 	      checkForMissingParameter(cluPublicationId, "cluPublicationId");
566 	      CluPublication cluPublication = luDao.fetch(CluPublication.class, cluPublicationId);
567 	      return LuServiceAssembler.toCluPublicationInfo(cluPublication);
568 	}
569 
570 	// **** Results
571 
572 	@Override
573 	public CluResultInfo getCluResult(String cluResultId)
574 			throws DoesNotExistException, InvalidParameterException,
575 			MissingParameterException, OperationFailedException {
576 
577 		checkForMissingParameter(cluResultId, "cluResultId");
578 
579 		CluResult cluResult = luDao.fetch(CluResult.class, cluResultId);
580 		return LuServiceAssembler.toCluResultInfo(cluResult);
581 	}
582 
583 	@Override
584 	public List<CluResultInfo> getCluResultByClu(String cluId)
585 			throws DoesNotExistException, InvalidParameterException,
586 			MissingParameterException, OperationFailedException {
587 
588 		checkForMissingParameter(cluId, "cluId");
589 
590 		return LuServiceAssembler.toCluResultInfos(luDao
591 				.getCluResultByClu(cluId));
592 	}
593 
594 	@Override
595 	public List<String> getCluIdsByResultUsageType(String resultUsageTypeKey)
596 			throws DoesNotExistException, InvalidParameterException,
597 			MissingParameterException, OperationFailedException {
598 		return luDao.getCluIdsByResultUsageType(resultUsageTypeKey);
599 	}
600 
601 	@Override
602 	public List<String> getCluIdsByResultComponent(String resultComponentId)
603 			throws DoesNotExistException, InvalidParameterException,
604 			MissingParameterException, OperationFailedException {
605 		return luDao.getCluIdsByResultComponentId(resultComponentId);
606 	}
607 
608 	// **** Learning Objectives
609 
610 	@Override
611 	public CluLoRelationInfo getCluLoRelation(String cluLoRelationId)
612 			throws DoesNotExistException, InvalidParameterException,
613 			MissingParameterException, OperationFailedException,
614 			PermissionDeniedException {
615 
616 		checkForMissingParameter(cluLoRelationId, "cluLoRelationId");
617 
618 		CluLoRelation reltn = luDao.fetch(CluLoRelation.class, cluLoRelationId);
619 		return LuServiceAssembler.toCluLoRelationInfo(reltn);
620 
621 	}
622 
623 	@Override
624 	public List<CluLoRelationInfo> getCluLoRelationsByClu(String cluId)
625 			throws DoesNotExistException, InvalidParameterException,
626 			MissingParameterException, OperationFailedException {
627 
628 		checkForMissingParameter(cluId, "cluId");
629 		List<CluLoRelation> cluLoRelations = luDao
630 				.getCluLoRelationsByClu(cluId);
631 		return LuServiceAssembler.toCluLoRelationInfos(cluLoRelations);
632 
633 	}
634 
635 	@Override
636 	public List<CluLoRelationInfo> getCluLoRelationsByLo(String loId)
637 			throws DoesNotExistException, InvalidParameterException,
638 			MissingParameterException, OperationFailedException {
639 		checkForMissingParameter(loId, "loId");
640 		List<CluLoRelation> cluLoRelations = luDao.getCluLoRelationsByLo(loId);
641 		return LuServiceAssembler.toCluLoRelationInfos(cluLoRelations);
642 	}
643 
644 	// *** Resources
645 
646 	@Override
647 	public List<String> getResourceRequirementsForCluId(String cluId)
648 			throws DoesNotExistException, InvalidParameterException,
649 			MissingParameterException, OperationFailedException {
650 	      throw new UnsupportedOperationException("Method not yet implemented!");
651 	}
652 
653 	// *** Sets
654 
655 	@Override
656 	public CluSetInfo getCluSetInfo(String cluSetId)
657 			throws DoesNotExistException, InvalidParameterException,
658 			MissingParameterException, OperationFailedException,
659 			PermissionDeniedException {
660 		checkForMissingParameter(cluSetId, "cluSetId");
661 		CluSet cluSet = luDao.fetch(CluSet.class, cluSetId);
662 		CluSetInfo cluSetInfo = LuServiceAssembler.toCluSetInfo(cluSet);
663 		setMembershipQuerySearchResult(cluSetInfo);
664 		return cluSetInfo;
665 	}
666 
667 	@Override
668 	public CluSetTreeViewInfo getCluSetTreeView(String cluSetId)
669 			throws DoesNotExistException, InvalidParameterException,
670 			MissingParameterException, OperationFailedException,
671 			PermissionDeniedException {
672 
673 		checkForMissingParameter(cluSetId, "cluSetId");
674 		CluSetInfo cluSet = getCluSetInfo(cluSetId);
675 		if (cluSet == null) {
676 			return null;
677 		}
678 
679 		CluSetTreeViewInfo cluSetTreeView = new CluSetTreeViewInfo();
680 		getCluSetTreeViewHelper(cluSet, cluSetTreeView);
681 		return cluSetTreeView;
682 	}
683 
684 	/**
685 	 * Go through the list of CluSets and retrieve all the information regarding child
686 	 * Clu Sets and associated Clus
687 	 *
688 	 * @param cluSetInfo
689 	 * @param cluSetTreeViewInfo
690 	 * @throws DoesNotExistException
691 	 * @throws InvalidParameterException
692 	 * @throws MissingParameterException
693 	 * @throws OperationFailedException
694 	 * @throws PermissionDeniedException
695 	 */
696 	private void getCluSetTreeViewHelper(CluSetInfo cluSetInfo,
697 			CluSetTreeViewInfo cluSetTreeViewInfo) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
698 		cluSetTreeViewInfo.setName(cluSetInfo.getName());
699 		cluSetTreeViewInfo.setDescr(cluSetInfo.getDescr());
700 		cluSetTreeViewInfo.setEffectiveDate(cluSetInfo.getEffectiveDate());
701 		cluSetTreeViewInfo.setExpirationDate(cluSetInfo.getExpirationDate());
702 		cluSetTreeViewInfo.setAdminOrg(cluSetInfo.getAdminOrg());
703 		cluSetTreeViewInfo.setIsReusable(cluSetInfo.getIsReusable());
704 		cluSetTreeViewInfo.setIsReferenceable(cluSetInfo.getIsReferenceable());
705 		cluSetTreeViewInfo.setMetaInfo(cluSetInfo.getMetaInfo());
706 		cluSetTreeViewInfo.setAttributes(cluSetInfo.getAttributes());
707 		cluSetTreeViewInfo.setType(cluSetInfo.getType());
708 		cluSetTreeViewInfo.setState(cluSetInfo.getState());
709 		cluSetTreeViewInfo.setId(cluSetInfo.getId());
710 
711 		if (!cluSetInfo.getCluSetIds().isEmpty()) {
712 			for (String cluSetId : cluSetInfo.getCluSetIds()) {
713 				CluSetInfo subCluSet = getCluSetInfo(cluSetId);
714 				List<CluSetTreeViewInfo> cluSets =
715                     cluSetTreeViewInfo.getCluSets() == null ?
716                             new ArrayList<CluSetTreeViewInfo>(0) : cluSetTreeViewInfo.getCluSets();
717 
718                 CluSetTreeViewInfo subCluSetTreeViewInfo = new CluSetTreeViewInfo();
719                 getCluSetTreeViewHelper(subCluSet, subCluSetTreeViewInfo);
720                 cluSets.add(subCluSetTreeViewInfo);
721 
722                 cluSetTreeViewInfo.setCluSets(cluSets);
723 			}
724 		}
725 		List<CluInfo> clus = new ArrayList<CluInfo>();
726 		for (String cluId : cluSetInfo.getCluIds()) {
727 			if(cluId!=null){
728                 //Optimized version of clu translation. It seems like for now we only need the following information.
729                 //If more information is needed, then appropriate method in assembler has to be used.
730                 Clu clu = luDao.getCurrentCluVersion(cluId);
731                 CluInfo cluInfo = new CluInfo();
732                 cluInfo.setId(clu.getId());
733                 cluInfo.setType(clu.getLuType().getId());
734                 cluInfo.setOfficialIdentifier(LuServiceAssembler.toCluIdentifierInfo(clu.getOfficialIdentifier()));
735 				clus.add(cluInfo);
736 			}
737 		}
738 		cluSetTreeViewInfo.setClus(clus);
739 	}
740 
741 	@Override
742 	public List<CluSetInfo> getCluSetInfoByIdList(List<String> cluSetIdList)
743 			throws DoesNotExistException, InvalidParameterException,
744 			MissingParameterException, OperationFailedException,
745 			PermissionDeniedException {
746 		checkForMissingParameter(cluSetIdList, "cluSetIdList");
747 		checkForEmptyList(cluSetIdList, "cluSetIdList");
748 		List<CluSet> cluSets = luDao.getCluSetInfoByIdList(cluSetIdList);
749 		return LuServiceAssembler.toCluSetInfos(cluSets);
750 	}
751 
752 	@Override
753 	public List<String> getCluSetIdsFromCluSet(String cluSetId)
754 			throws DoesNotExistException, InvalidParameterException,
755 			MissingParameterException, OperationFailedException,
756 			PermissionDeniedException {
757 		checkForMissingParameter(cluSetId, "cluSetId");
758 		CluSet cluSet = luDao.fetch(CluSet.class, cluSetId);
759 		List<String> ids = new ArrayList<String>(cluSet.getCluVerIndIds().size());
760 		if(cluSet.getCluSets()!=null){
761 			for (CluSet cluSet2 : cluSet.getCluSets()) {
762 				ids.add(cluSet2.getId());
763 			}
764 		}
765 		return ids;
766 	}
767 
768 	@Override
769 	public Boolean isCluSetDynamic(String cluSetId)
770 			throws DoesNotExistException, InvalidParameterException,
771 			MissingParameterException, OperationFailedException,
772 			PermissionDeniedException {
773 	      throw new UnsupportedOperationException("Method not yet implemented!");
774 	}
775 
776 	@Override
777 	public List<CluInfo> getClusFromCluSet(String cluSetId)
778 			throws DoesNotExistException, InvalidParameterException,
779 			MissingParameterException, OperationFailedException,
780 			PermissionDeniedException {
781 		checkForMissingParameter(cluSetId, "cluSetId");
782 		CluSet cluSet = luDao.fetch(CluSet.class, cluSetId);
783 		List<CluInfo> clus = new ArrayList<CluInfo>(cluSet.getCluVerIndIds().size());
784 		for (CluSetJoinVersionIndClu cluSetJnClu : cluSet.getCluVerIndIds()) {
785 			clus.add(LuServiceAssembler.toCluInfo(luDao.getCurrentCluVersion(cluSetJnClu.getCluVersionIndId())));
786 		}
787 		return clus;
788 	}
789 
790 	@Override
791 	public List<String> getCluIdsFromCluSet(String cluSetId)
792 			throws DoesNotExistException, InvalidParameterException,
793 			MissingParameterException, OperationFailedException,
794 			PermissionDeniedException {
795 		checkForMissingParameter(cluSetId, "cluSetId");
796 		CluSet cluSet = luDao.fetch(CluSet.class, cluSetId);
797 		List<String> ids = new ArrayList<String>(cluSet.getCluVerIndIds().size());
798 		for (CluSetJoinVersionIndClu cluSetJnClu : cluSet.getCluVerIndIds()) {
799 			ids.add(cluSetJnClu.getCluVersionIndId());
800 		}
801 		return ids;
802 	}
803 
804 	@Override
805 	public List<CluInfo> getAllClusInCluSet(String cluSetId)
806 			throws DoesNotExistException, InvalidParameterException,
807 			MissingParameterException, OperationFailedException,
808 			PermissionDeniedException {
809 		checkForMissingParameter(cluSetId, "cluSetId");
810 		List<String> cluIndIds = new ArrayList<String>();
811 		CluSet cluSet = luDao.fetch(CluSet.class, cluSetId);
812 		findClusInCluSet(cluIndIds, cluSet);
813 		List<CluInfo> infos = new ArrayList<CluInfo>(cluIndIds.size());
814 		for (String cluIndId : cluIndIds) {
815 			infos.add(LuServiceAssembler.toCluInfo(luDao.getCurrentCluVersion(cluIndId)));
816 		}
817 		return infos;
818 	}
819 
820 	@Override
821 	public List<String> getAllCluIdsInCluSet(String cluSetId)
822 			throws DoesNotExistException, InvalidParameterException,
823 			MissingParameterException, OperationFailedException,
824 			PermissionDeniedException {
825 		checkForMissingParameter(cluSetId, "cluSetId");
826 		List<String> ids = new ArrayList<String>();
827 		CluSet cluSet = luDao.fetch(CluSet.class, cluSetId);
828 		findClusInCluSet(ids, cluSet);
829 		return ids;
830 	}
831 
832 	@Override
833 	public Boolean isCluInCluSet(String cluId, String cluSetId)
834 			throws DoesNotExistException, InvalidParameterException,
835 			MissingParameterException, OperationFailedException,
836 			PermissionDeniedException {
837 		checkForMissingParameter(cluId, "cluId");
838 		checkForMissingParameter(cluSetId, "cluSetId");
839 		return luDao.isCluInCluSet(cluId, cluSetId);
840 	}
841 
842 	// ******** LUI OPERATIONS
843 	// *** Core
844 
845 	@Override
846 	public LuiInfo getLui(String luiId) throws DoesNotExistException,
847 			InvalidParameterException, MissingParameterException,
848 			OperationFailedException {
849 
850 		checkForMissingParameter(luiId, "luiId");
851 
852 		Lui lui = luDao.fetch(Lui.class, luiId);
853 		return LuServiceAssembler.toLuiInfo(lui);
854 	}
855 
856 	@Override
857 	public List<LuiInfo> getLuisByIdList(List<String> luiIdList)
858 			throws DoesNotExistException, InvalidParameterException,
859 			MissingParameterException, OperationFailedException {
860 		checkForMissingParameter(luiIdList, "luiIdList");
861 		checkForEmptyList(luiIdList, "luiIdList");
862 		List<Lui> luis = luDao.getLuisByIdList(luiIdList);
863 		return LuServiceAssembler.toLuiInfos(luis);
864 	}
865 
866 	@Override
867 	public List<LuiInfo> getLuisInAtpByCluId(String cluId, String atpKey)
868 			throws DoesNotExistException, InvalidParameterException,
869 			MissingParameterException, OperationFailedException {
870 	      throw new UnsupportedOperationException("Method not yet implemented!");
871 	}
872 
873 	@Override
874 	public List<String> getLuiIdsByCluId(String cluId)
875 			throws DoesNotExistException, InvalidParameterException,
876 			MissingParameterException, OperationFailedException {
877 
878 		checkForMissingParameter(cluId, "cluId");
879 
880 		return luDao.getLuiIdsByCluId(cluId);
881 	}
882 
883 	@Override
884 	public List<String> getLuiIdsInAtpByCluId(String cluId, String atpKey)
885 			throws DoesNotExistException, InvalidParameterException,
886 			MissingParameterException, OperationFailedException {
887 
888 		checkForMissingParameter(cluId, "cluId");
889 		checkForMissingParameter(atpKey, "atpKey");
890 		return luDao.getLuiIdsInAtpByCluId(cluId, atpKey);
891 	}
892 
893 	// *** Relations
894 
895 	@Override
896 	public List<String> getAllowedLuLuRelationTypesByLuiId(String luiId,
897 			String relatedLuiId) throws DoesNotExistException,
898 			InvalidParameterException, MissingParameterException,
899 			OperationFailedException {
900 
901 		checkForMissingParameter(luiId, "luiId");
902 		checkForMissingParameter(relatedLuiId, "relatedLuiId");
903 
904 		return luDao.getAllowedLuLuRelationTypesByLuiId(luiId, relatedLuiId);
905 	}
906 
907 	@Override
908 	public List<LuiInfo> getLuisByRelation(String luiId,
909 			String luLuRelationTypeKey) throws DoesNotExistException,
910 			InvalidParameterException, MissingParameterException,
911 			OperationFailedException {
912 		checkForMissingParameter(luiId, "luiId");
913 		checkForMissingParameter(luLuRelationTypeKey, "luLuRelationTypeKey");
914 
915 		return LuServiceAssembler.toLuiInfos(luDao.getLuisByRelationType(luiId,
916 				luLuRelationTypeKey));
917 	}
918 
919 	@Override
920 	public List<String> getLuiIdsByRelation(String luiId,
921 			String luLuRelationTypeKey) throws DoesNotExistException,
922 			InvalidParameterException, MissingParameterException,
923 			OperationFailedException {
924 		checkForMissingParameter(luiId, "luiId");
925 		checkForMissingParameter(luLuRelationTypeKey, "luLuRelationTypeKey");
926 
927 		return luDao.getLuiIdsByRelationType(luiId, luLuRelationTypeKey);
928 	}
929 
930 	@Override
931 	public List<LuiInfo> getRelatedLuisByLuiId(String luiId,
932 			String luLuRelationTypeKey) throws DoesNotExistException,
933 			InvalidParameterException, MissingParameterException,
934 			OperationFailedException {
935 		checkForMissingParameter(luiId, "luiId");
936 		checkForMissingParameter(luLuRelationTypeKey, "luLuRelationTypeKey");
937 		List<Lui> relatedLuis = luDao.getRelatedLuisByLuiId(luiId,
938 				luLuRelationTypeKey);
939 		return LuServiceAssembler.toLuiInfos(relatedLuis);
940 	}
941 
942 	@Override
943 	public List<String> getRelatedLuiIdsByLuiId(String luiId,
944 			String luLuRelationTypeKey) throws DoesNotExistException,
945 			InvalidParameterException, MissingParameterException,
946 			OperationFailedException {
947 		checkForMissingParameter(luiId, "luiId");
948 		checkForMissingParameter(luLuRelationTypeKey, "luLuRelationTypeKey");
949 		List<String> relatedLuiIds = luDao.getRelatedLuiIdsByLuiId(luiId,
950 				luLuRelationTypeKey);
951 		return relatedLuiIds;
952 	}
953 
954 	@Override
955 	public LuiLuiRelationInfo getLuiLuiRelation(String luiLuiRelationId)
956 			throws DoesNotExistException, InvalidParameterException,
957 			MissingParameterException, OperationFailedException {
958 		checkForMissingParameter(luiLuiRelationId, "luiLuiRelationId");
959 		LuiLuiRelation luiLuiRelation = luDao.fetch(LuiLuiRelation.class,
960 				luiLuiRelationId);
961 		return LuServiceAssembler.toLuiLuiRelationInfo(luiLuiRelation);
962 	}
963 
964 	@Override
965 	public List<LuiLuiRelationInfo> getLuiLuiRelationsByLui(String luiId)
966 			throws DoesNotExistException, InvalidParameterException,
967 			MissingParameterException, OperationFailedException {
968 		checkForMissingParameter(luiId, "luiId");
969 		List<LuiLuiRelation> entities = luDao.getLuiLuiRelations(luiId);
970 		return LuServiceAssembler.toLuiLuiRelationInfos(entities);
971 	}
972 
973 	/**************************************************************************
974 	 * MAINTENANCE OPERATIONS *
975 	 **************************************************************************/
976 
977 	@Override
978 	public List<ValidationResultInfo> validateClu(String validationType,
979 			CluInfo cluInfo) throws DoesNotExistException,
980 			InvalidParameterException, MissingParameterException,
981 			OperationFailedException {
982 		checkForMissingParameter(validationType, "validationType");
983 		checkForMissingParameter(cluInfo, "cluInfo");
984 
985         ObjectStructureDefinition objStructure = this.getObjectStructure(CluInfo.class.getName());
986         Validator defaultValidator = validatorFactory.getValidator();
987         List<ValidationResultInfo> validationResults = defaultValidator.validateObject(cluInfo, objStructure);
988         
989         return validationResults;
990 	}
991 
992 	@Override
993 	@Transactional(readOnly=false)
994 	public CluInfo createClu(String luTypeKey, CluInfo cluInfo)
995 			throws AlreadyExistsException, DataValidationErrorException,
996 			DoesNotExistException, InvalidParameterException,
997 			MissingParameterException, OperationFailedException,
998 			PermissionDeniedException {
999 		Clu clu = toCluForCreate(luTypeKey,cluInfo);
1000 		//Set current (since this is brand new and every verIndId needs one current)
1001 		if(clu.getVersion() == null){
1002 			clu.setVersion(new Version());
1003 		}
1004 		clu.getVersion().setCurrentVersionStart(new Date());
1005 		luDao.create(clu);
1006 		return LuServiceAssembler.toCluInfo(clu);
1007 	}
1008 	
1009 	public Clu toCluForCreate(String luTypeKey, CluInfo cluInfo)
1010 			throws AlreadyExistsException, DataValidationErrorException,
1011 			DoesNotExistException, InvalidParameterException,
1012 			MissingParameterException, OperationFailedException,
1013 			PermissionDeniedException {
1014 		checkForMissingParameter(luTypeKey, "luTypeKey");
1015 		checkForMissingParameter(cluInfo, "cluInfo");
1016 
1017 		// Validate CLU
1018 		List<ValidationResultInfo> val = validateClu("SYSTEM", cluInfo);
1019 		if(null != val && val.size() > 0) {
1020 			throw new DataValidationErrorException("Validation error!", val);
1021 		}
1022 
1023 		Clu clu = new Clu();
1024 
1025 		LuType luType = luDao.fetch(LuType.class, luTypeKey);
1026 		clu.setLuType(luType);
1027 
1028 		if (cluInfo.getOfficialIdentifier() != null) {
1029 			clu.setOfficialIdentifier(LuServiceAssembler.createOfficialIdentifier(cluInfo, luDao));
1030 		}
1031 		clu.setAlternateIdentifiers(LuServiceAssembler.createAlternateIdentifiers(cluInfo, luDao));
1032 		if (cluInfo.getDescr() != null) {
1033 		    LuRichText descr = LuServiceAssembler.toRichText(LuRichText.class, cluInfo.getDescr());
1034 		    if (descr.getPlain() != null || descr.getFormatted() != null) {
1035 		        clu.setDescr(descr);
1036 		    }
1037 		}
1038 
1039 		if (clu.getAdminOrgs() == null) {
1040 			clu.setAdminOrgs(new ArrayList<CluAdminOrg>(0));
1041 		}
1042 		List<CluAdminOrg> adminOrgs = clu.getAdminOrgs();
1043 		for (AdminOrgInfo orgInfo : cluInfo.getAdminOrgs()) {
1044 			CluAdminOrg instructor = new CluAdminOrg();
1045 			BeanUtils.copyProperties(orgInfo, instructor,
1046 					new String[] { "attributes" });
1047 			instructor.setAttributes(LuServiceAssembler.toGenericAttributes(
1048 					CluAdminOrgAttribute.class, orgInfo.getAttributes(),
1049 					instructor, luDao));
1050 			instructor.setClu(clu);
1051 			adminOrgs.add(instructor);
1052 		}
1053 
1054 		if (cluInfo.getPrimaryInstructor() != null) {
1055 			CluInstructor primaryInstructor = new CluInstructor();
1056 			BeanUtils.copyProperties(cluInfo.getPrimaryInstructor(),
1057 					primaryInstructor, new String[] { "attributes" });
1058 			primaryInstructor.setAttributes(LuServiceAssembler
1059 					.toGenericAttributes(CluInstructorAttribute.class, cluInfo
1060 							.getPrimaryInstructor().getAttributes(),
1061 							primaryInstructor, luDao));
1062 			clu.setPrimaryInstructor(primaryInstructor);
1063 		}
1064 
1065 		if (clu.getInstructors() == null) {
1066 			clu.setInstructors(new ArrayList<CluInstructor>(0));
1067 		}
1068 		List<CluInstructor> instructors = clu.getInstructors();
1069 		for (CluInstructorInfo instructorInfo : cluInfo.getInstructors()) {
1070 			CluInstructor instructor = new CluInstructor();
1071 			BeanUtils.copyProperties(instructorInfo, instructor,
1072 					new String[] { "attributes" });
1073 			instructor.setAttributes(LuServiceAssembler.toGenericAttributes(
1074 					CluInstructorAttribute.class, instructorInfo
1075 							.getAttributes(), instructor, luDao));
1076 			instructors.add(instructor);
1077 		}
1078 
1079 		if (cluInfo.getStdDuration() != null) {
1080 			clu.setStdDuration(LuServiceAssembler.toTimeAmount(cluInfo
1081 					.getStdDuration()));
1082 		}
1083 
1084 		if (clu.getLuCodes() == null) {
1085 			clu.setLuCodes(new ArrayList<LuCode>(0));
1086 		}
1087 		List<LuCode> luCodes = clu.getLuCodes();
1088 		for (LuCodeInfo luCodeInfo : cluInfo.getLuCodes()) {
1089 			LuCode luCode = new LuCode();
1090 			luCode.setAttributes(LuServiceAssembler.toGenericAttributes(
1091 					LuCodeAttribute.class, luCodeInfo.getAttributes(), luCode,
1092 					luDao));
1093 			BeanUtils.copyProperties(luCodeInfo, luCode, new String[] {
1094 					"attributes", "metaInfo" });
1095 			luCode.setDescr(luCodeInfo.getDescr());
1096 			luCode.setClu(clu);
1097 			luCodes.add(luCode);
1098 		}
1099 
1100 		if (clu.getOfferedAtpTypes() == null) {
1101 			clu.setOfferedAtpTypes(new ArrayList<CluAtpTypeKey>(0));
1102 		}
1103 		List<CluAtpTypeKey> offeredAtpTypes = clu.getOfferedAtpTypes();
1104 		for (String atpTypeKey : cluInfo.getOfferedAtpTypes()) {
1105 			CluAtpTypeKey cluAtpTypeKey = new CluAtpTypeKey();
1106 			cluAtpTypeKey.setAtpTypeKey(atpTypeKey);
1107 			cluAtpTypeKey.setClu(clu);
1108 			offeredAtpTypes.add(cluAtpTypeKey);
1109 		}
1110 
1111 		// FEE INFO
1112 		if (cluInfo.getFeeInfo() != null) {
1113 			CluFee cluFee = null;
1114 			try {
1115 				cluFee = LuServiceAssembler.toCluFee(clu, false, cluInfo
1116 						.getFeeInfo(), luDao);
1117 			} catch (VersionMismatchException e) {
1118 				// Version Mismatch Should Happen only for updates
1119 			}
1120 			clu.setFee(cluFee);
1121 		}
1122 
1123 		if (cluInfo.getAccountingInfo() != null) {
1124 			CluAccounting cluAccounting = new CluAccounting();
1125 			cluAccounting.setAttributes(LuServiceAssembler.toGenericAttributes(
1126 					CluAccountingAttribute.class, cluInfo.getAccountingInfo()
1127 							.getAttributes(), cluAccounting, luDao));
1128 			cluAccounting.setAffiliatedOrgs(LuServiceAssembler
1129 					.toAffiliatedOrgs(false, cluAccounting.getAffiliatedOrgs(),
1130 							cluInfo.getAccountingInfo().getAffiliatedOrgs(),
1131 							luDao));
1132 			clu.setAccounting(cluAccounting);
1133 		}
1134 
1135 		clu.setAttributes(LuServiceAssembler.toGenericAttributes(
1136 				CluAttribute.class, cluInfo.getAttributes(), clu, luDao));
1137 
1138 
1139 		if (cluInfo.getIntensity() != null) {
1140 			clu.setIntensity(LuServiceAssembler
1141 					.toAmount(cluInfo.getIntensity()));
1142 		}
1143 
1144 		if (clu.getCampusLocations() == null) {
1145 			clu.setCampusLocations(new ArrayList<CluCampusLocation>(0));
1146 		}
1147 		List<CluCampusLocation> locations = clu.getCampusLocations();
1148 		for (String locationName : cluInfo.getCampusLocations()) {
1149 			CluCampusLocation location = new CluCampusLocation();
1150 			location.setCampusLocation(locationName);
1151 			location.setClu(clu);
1152 			locations.add(location);
1153 		}
1154 
1155 		if (clu.getAccreditations() == null) {
1156 			clu.setAccreditations(new ArrayList<CluAccreditation>(0));
1157 		}
1158 		List<CluAccreditation> accreditations = clu.getAccreditations();
1159 		for (AccreditationInfo accreditationInfo : cluInfo.getAccreditations()) {
1160 			CluAccreditation accreditation = new CluAccreditation();
1161 			BeanUtils.copyProperties(accreditationInfo, accreditation,
1162 					new String[] { "attributes" });
1163 			accreditation.setAttributes(LuServiceAssembler.toGenericAttributes(
1164 					CluAccreditationAttribute.class, accreditationInfo
1165 							.getAttributes(), accreditation, luDao));
1166 			accreditations.add(accreditation);
1167 		}
1168 		
1169 		// Now copy all not standard properties
1170 		BeanUtils.copyProperties(cluInfo, clu, new String[] { "luType",
1171 				"officialIdentifier", "alternateIdentifiers", "descr",
1172 				"luCodes", "primaryInstructor", "instructors", "stdDuration",
1173 				"offeredAtpTypes", "feeInfo", "accountingInfo", "attributes",
1174 				"metaInfo", "versionInfo", "intensity",
1175 				"campusLocations", "accreditations",
1176 				"adminOrgs" });
1177 
1178 		return clu;
1179 	}
1180 
1181 	@Override
1182 	@Transactional(readOnly=false)
1183 	public CluInfo updateClu(String cluId, CluInfo cluInfo)
1184 			throws DataValidationErrorException, DoesNotExistException,
1185 			InvalidParameterException, MissingParameterException,
1186 			OperationFailedException, PermissionDeniedException,
1187 			VersionMismatchException {
1188 
1189 		checkForMissingParameter(cluId, "cluId");
1190 		checkForMissingParameter(cluInfo, "cluInfo");
1191 
1192 		// Validate CLU
1193 		List<ValidationResultInfo> val = validateClu("SYSTEM", cluInfo);
1194 		if(null != val && val.size() > 0) {
1195 			throw new DataValidationErrorException("Validation error!", val);
1196 		}
1197 
1198 		Clu clu = luDao.fetch(Clu.class, cluId);
1199 
1200 		if (!String.valueOf(clu.getVersionNumber()).equals(
1201 				cluInfo.getMetaInfo().getVersionInd())) {
1202 			throw new VersionMismatchException(
1203 					"Clu to be updated is not the current version");
1204 		}
1205 
1206 		LuType luType = luDao.fetch(LuType.class, cluInfo.getType());
1207 		clu.setLuType(luType);
1208 
1209 		if (cluInfo.getOfficialIdentifier() != null) {
1210 		    LuServiceAssembler.updateOfficialIdentifier(clu, cluInfo, luDao);
1211 		} else if (clu.getOfficialIdentifier() != null) {
1212 			luDao.delete(clu.getOfficialIdentifier());
1213 		}
1214 
1215 		// Update the list of Alternate Identifiers
1216 		// Get a map of Id->object of all the currently persisted objects in the
1217 		// list
1218 		Map<String, CluIdentifier> oldAltIdMap = new HashMap<String, CluIdentifier>();
1219 		LuServiceAssembler.updateAlternateIdentifier(oldAltIdMap, clu, cluInfo, luDao);
1220 		// Now delete anything left over
1221 		for (Entry<String, CluIdentifier> entry : oldAltIdMap.entrySet()) {
1222 			luDao.delete(entry.getValue());
1223 		}
1224 
1225 		if (cluInfo.getDescr() != null && (cluInfo.getDescr().getPlain() != null || cluInfo.getDescr().getFormatted() != null)) {
1226 			if (clu.getDescr() == null) {
1227 				clu.setDescr(new LuRichText());
1228 			}
1229 			BeanUtils.copyProperties(cluInfo.getDescr(), clu.getDescr());
1230 		} else if (clu.getDescr() != null) {
1231 			luDao.delete(clu.getDescr());
1232 			clu.setDescr(null);//TODO is the is the best method of doing this? what if the user passes in a new made up id, does that mean we have orphaned richtexts?
1233 		}
1234 
1235 		if (cluInfo.getPrimaryInstructor() != null) {
1236 			if (clu.getPrimaryInstructor() == null) {
1237 				clu.setPrimaryInstructor(new CluInstructor());
1238 			}
1239 			BeanUtils.copyProperties(cluInfo.getPrimaryInstructor(), clu
1240 					.getPrimaryInstructor(), new String[] { "attributes" });
1241 			clu.getPrimaryInstructor().setAttributes(
1242 					LuServiceAssembler.toGenericAttributes(
1243 							CluInstructorAttribute.class, cluInfo
1244 									.getPrimaryInstructor().getAttributes(),
1245 							clu.getPrimaryInstructor(), luDao));
1246 		} else if (clu.getPrimaryInstructor() != null) {
1247 			luDao.delete(clu.getPrimaryInstructor());
1248 		}
1249 
1250 		// Update the List of instructors
1251 		// Get a map of Id->object of all the currently persisted objects in the
1252 		// list
1253 		Map<String, CluInstructor> oldInstructorMap = new HashMap<String, CluInstructor>();
1254 		for (CluInstructor cluInstructor : clu.getInstructors()) {
1255 			oldInstructorMap.put(cluInstructor.getOrgId() + "_"
1256 					+ cluInstructor.getPersonId(), cluInstructor);
1257 		}
1258 		clu.getInstructors().clear();
1259 
1260 		// Loop through the new list, if the item exists already update and
1261 		// remove from the list
1262 		// otherwise create a new entry
1263 		for (CluInstructorInfo instructorInfo : cluInfo.getInstructors()) {
1264 			CluInstructor cluInstructor = oldInstructorMap
1265 					.remove(instructorInfo.getOrgId() + "_"
1266 							+ instructorInfo.getPersonId());
1267 			if (cluInstructor == null) {
1268 				cluInstructor = new CluInstructor();
1269 			}
1270 			// Do Copy
1271 			BeanUtils.copyProperties(instructorInfo, cluInstructor,
1272 					new String[] { "attributes" });
1273 			cluInstructor.setAttributes(LuServiceAssembler.toGenericAttributes(
1274 					CluInstructorAttribute.class, instructorInfo
1275 							.getAttributes(), cluInstructor, luDao));
1276 			clu.getInstructors().add(cluInstructor);
1277 		}
1278 
1279 		// Now delete anything left over
1280 		for (Entry<String, CluInstructor> entry : oldInstructorMap.entrySet()) {
1281 			luDao.delete(entry.getValue());
1282 		}
1283 
1284 		if (cluInfo.getStdDuration() != null) {
1285 			if (clu.getStdDuration() == null) {
1286 				clu.setStdDuration(new TimeAmount());
1287 			}
1288 			BeanUtils.copyProperties(cluInfo.getStdDuration(), clu
1289 					.getStdDuration());
1290 		} else if (clu.getStdDuration() != null) {
1291 			luDao.delete(clu.getStdDuration());
1292 		}
1293 
1294 		// Update the LuCodes
1295 		// Get a map of Id->object of all the currently persisted objects in the
1296 		// list
1297 		Map<String, LuCode> oldLuCodeMap = new HashMap<String, LuCode>();
1298 		for (LuCode luCode : clu.getLuCodes()) {
1299 			oldLuCodeMap.put(luCode.getId(), luCode);
1300 		}
1301 		clu.getLuCodes().clear();
1302 
1303 		// Loop through the new list, if the item exists already update and
1304 		// remove from the list
1305 		// otherwise create a new entry
1306 		for (LuCodeInfo luCodeInfo : cluInfo.getLuCodes()) {
1307 			LuCode luCode = oldLuCodeMap.remove(luCodeInfo.getId());
1308 			if (luCode == null) {
1309 				luCode = new LuCode();
1310 			} else {
1311 				if (!String.valueOf(luCode.getVersionNumber()).equals(
1312 						luCodeInfo.getMetaInfo().getVersionInd())) {
1313 					throw new VersionMismatchException(
1314 							"LuCode to be updated is not the current version");
1315 				}
1316 			}
1317 			// Do Copy
1318 			luCode.setAttributes(LuServiceAssembler.toGenericAttributes(
1319 					LuCodeAttribute.class, luCodeInfo.getAttributes(), luCode,
1320 					luDao));
1321 			BeanUtils.copyProperties(luCodeInfo, luCode, new String[] {
1322 					"attributes", "metaInfo" });
1323 			luCode.setDescr(luCodeInfo.getDescr());
1324 			luCode.setClu(clu);
1325 			clu.getLuCodes().add(luCode);
1326 		}
1327 
1328 		// Now delete anything left over
1329 		for (Entry<String, LuCode> entry : oldLuCodeMap.entrySet()) {
1330 			luDao.delete(entry.getValue());
1331 		}
1332 
1333 		// Update the list of AtpTypeKeys
1334 		// Get a map of Id->object of all the currently persisted objects in the
1335 		// list
1336 		Map<String, CluAtpTypeKey> oldOfferedAtpTypesMap = new HashMap<String, CluAtpTypeKey>();
1337 		for (CluAtpTypeKey cluAtpTypeKey : clu.getOfferedAtpTypes()) {
1338 			oldOfferedAtpTypesMap.put(cluAtpTypeKey.getAtpTypeKey(),
1339 					cluAtpTypeKey);
1340 		}
1341 		clu.getOfferedAtpTypes().clear();
1342 
1343 		// Loop through the new list, if the item exists already update and
1344 		// remove from the list
1345 		// otherwise create a new entry
1346 		for (String atpTypeKey : cluInfo.getOfferedAtpTypes()) {
1347 			CluAtpTypeKey cluAtpTypeKey = oldOfferedAtpTypesMap
1348 					.remove(atpTypeKey);
1349 			if (cluAtpTypeKey == null) {
1350 				cluAtpTypeKey = new CluAtpTypeKey();
1351 			}
1352 			// Do Copy
1353 			cluAtpTypeKey.setAtpTypeKey(atpTypeKey);
1354 			cluAtpTypeKey.setClu(clu);
1355 			clu.getOfferedAtpTypes().add(cluAtpTypeKey);
1356 		}
1357 
1358 		// Now delete anything left over
1359 		for (Entry<String, CluAtpTypeKey> entry : oldOfferedAtpTypesMap
1360 				.entrySet()) {
1361 			luDao.delete(entry.getValue());
1362 		}
1363 
1364 		if (cluInfo.getFeeInfo() != null) {
1365 			if (clu.getFee() == null) {
1366 				clu.setFee(LuServiceAssembler.toCluFee(clu, false, cluInfo
1367 						.getFeeInfo(), luDao));
1368 			} else {
1369 				clu.setFee(LuServiceAssembler.toCluFee(clu, true, cluInfo
1370 						.getFeeInfo(), luDao));
1371 			}
1372 		} else if (clu.getFee() != null) {
1373 			luDao.delete(clu.getFee());
1374 			clu.setFee(null);
1375 		}
1376 
1377 		if (cluInfo.getAccountingInfo() != null) {
1378 			if (clu.getAccounting() == null) {
1379 				clu.setAccounting(new CluAccounting());
1380 			}
1381 			clu.getAccounting().setAttributes(
1382 					LuServiceAssembler.toGenericAttributes(
1383 							CluAccountingAttribute.class, cluInfo
1384 									.getAccountingInfo().getAttributes(), clu
1385 									.getAccounting(), luDao));
1386 			clu.getAccounting().setAffiliatedOrgs(LuServiceAssembler
1387 					.toAffiliatedOrgs(true, clu.getAccounting().getAffiliatedOrgs(),
1388 							cluInfo.getAccountingInfo().getAffiliatedOrgs(),
1389 							luDao));
1390 
1391 		} else if (clu.getAccounting() != null) {
1392 			clu.setAccounting(null);
1393 		}
1394 
1395 		clu.setAttributes(LuServiceAssembler.toGenericAttributes(
1396 				CluAttribute.class, cluInfo.getAttributes(), clu, luDao));
1397 
1398 		if (cluInfo.getIntensity() != null) {
1399 			if (clu.getIntensity() == null) {
1400 				clu.setIntensity(new Amount());
1401 			}
1402 			BeanUtils
1403 					.copyProperties(cluInfo.getIntensity(), clu.getIntensity());
1404 		} else if (clu.getIntensity() != null) {
1405 			luDao.delete(clu.getIntensity());
1406 		}
1407 
1408 		// Update the list of campusLocations
1409 		// Get a map of Id->object of all the currently persisted objects in the
1410 		// list
1411 		Map<String, CluCampusLocation> oldLocationsMap = new HashMap<String, CluCampusLocation>();
1412 		for (CluCampusLocation campus : clu.getCampusLocations()) {
1413 			oldLocationsMap.put(campus.getCampusLocation(), campus);
1414 		}
1415 		clu.getCampusLocations().clear();
1416 
1417 		// Loop through the new list, if the item exists already update and
1418 		// remove from the list
1419 		// otherwise create a new entry
1420 		for (String locationName : cluInfo.getCampusLocations()) {
1421 			CluCampusLocation location = oldLocationsMap.remove(locationName);
1422 			if (location == null) {
1423 				location = new CluCampusLocation();
1424 			}
1425 			// Do Copy
1426 			location.setCampusLocation(locationName);
1427 			location.setClu(clu);
1428 			clu.getCampusLocations().add(location);
1429 		}
1430 
1431 		// Now delete anything left over
1432 		for (Entry<String, CluCampusLocation> entry : oldLocationsMap
1433 				.entrySet()) {
1434 			luDao.delete(entry.getValue());
1435 		}
1436 
1437 		// Update the List of accreditations
1438 		// Get a map of Id->object of all the currently persisted objects in the
1439 		// list
1440 		Map<String, CluAccreditation> oldAccreditationMap = new HashMap<String, CluAccreditation>();
1441 		for (CluAccreditation cluAccreditation : clu.getAccreditations()) {
1442 			oldAccreditationMap.put(cluAccreditation.getId(),
1443 					cluAccreditation);
1444 		}
1445 		clu.getAccreditations().clear();
1446 
1447 		// Loop through the new list, if the item exists already update and
1448 		// remove from the list
1449 		// otherwise create a new entry
1450 		for (AccreditationInfo accreditationInfo : cluInfo.getAccreditations()) {
1451 			CluAccreditation cluAccreditation = null;
1452 			if(accreditationInfo.getId()!=null){
1453 				cluAccreditation = oldAccreditationMap.remove(accreditationInfo.getId());
1454 			}
1455 					
1456 			if (cluAccreditation == null) {
1457 				cluAccreditation = new CluAccreditation();
1458 			}
1459 			// Do Copy
1460 			BeanUtils.copyProperties(accreditationInfo, cluAccreditation,
1461 					new String[] { "attributes" });
1462 			cluAccreditation.setAttributes(LuServiceAssembler
1463 					.toGenericAttributes(CluAccreditationAttribute.class,
1464 							accreditationInfo.getAttributes(),
1465 							cluAccreditation, luDao));
1466 			clu.getAccreditations().add(cluAccreditation);
1467 		}
1468 
1469 		// Now delete anything left over
1470 		for (Entry<String, CluAccreditation> entry : oldAccreditationMap
1471 				.entrySet()) {
1472 			luDao.delete(entry.getValue());
1473 		}
1474 
1475 		// Update the List of alternate admin orgs
1476 		// Get a map of Id->object of all the currently persisted objects in the
1477 		// list
1478 		Map<String, CluAdminOrg> oldAdminOrgsMap = new HashMap<String, CluAdminOrg>();
1479 		if(clu.getAdminOrgs()!=null){
1480 			for (CluAdminOrg cluOrg : clu.getAdminOrgs()) {
1481 				oldAdminOrgsMap.put(cluOrg.getId(), cluOrg);
1482 			}
1483 		}
1484 		clu.setAdminOrgs(new ArrayList<CluAdminOrg>());
1485 
1486 		// Loop through the new list, if the item exists already update and
1487 		// remove from the list
1488 		// otherwise create a new entry
1489 		for (AdminOrgInfo orgInfo : cluInfo.getAdminOrgs()) {
1490 			CluAdminOrg cluOrg = null;
1491 			if(orgInfo.getId() != null){
1492 				cluOrg = oldAdminOrgsMap.remove(orgInfo.getId());
1493 			}
1494 			
1495 			if (cluOrg == null) {
1496 				cluOrg = new CluAdminOrg();
1497 			}
1498 			
1499 			// Do Copy
1500 			BeanUtils.copyProperties(orgInfo, cluOrg,
1501 					new String[] { "attributes","id" });
1502 			cluOrg.setAttributes(LuServiceAssembler.toGenericAttributes(
1503 					CluAdminOrgAttribute.class, orgInfo.getAttributes(),
1504 					cluOrg, luDao));
1505 			cluOrg.setClu(clu);
1506 			clu.getAdminOrgs().add(cluOrg);
1507 		}
1508 
1509 		for (Entry<String, CluAdminOrg> entry : oldAdminOrgsMap.entrySet()) {
1510 			luDao.delete(entry.getValue());
1511 		}
1512 
1513 		// Now copy all not standard properties
1514 		BeanUtils.copyProperties(cluInfo, clu, new String[] { "luType",
1515 				"officialIdentifier", "alternateIdentifiers", "descr",
1516 				"luCodes", "primaryInstructor", "instructors", "stdDuration",
1517 				"offeredAtpTypes", "feeInfo", "accountingInfo", "attributes",
1518 				"metaInfo","intensity",
1519 				"campusLocations", "accreditations",
1520 				"adminOrgs" });
1521 		Clu updated = null;
1522 		try {
1523 			updated = luDao.update(clu);
1524 		} catch (Exception e) {
1525 			logger.error("Exception occured: ", e);
1526 		}
1527 		return LuServiceAssembler.toCluInfo(updated);
1528 	}
1529 
1530 	@Override
1531 	@Transactional(readOnly=false)
1532 	public StatusInfo deleteClu(String cluId) throws DoesNotExistException,
1533 			InvalidParameterException, MissingParameterException,
1534 			DependentObjectsExistException, OperationFailedException,
1535 			PermissionDeniedException {
1536 		checkForMissingParameter(cluId, "cluId");
1537 
1538 		luDao.delete(Clu.class, cluId);
1539 
1540 		StatusInfo statusInfo = new StatusInfo();
1541 		statusInfo.setSuccess(true);
1542 
1543 		return statusInfo;
1544 	}
1545 
1546 	@Override
1547 	@Transactional(readOnly=false)
1548 	public CluInfo updateCluState(String cluId, String luState)
1549 			throws DataValidationErrorException, DoesNotExistException,
1550 			InvalidParameterException, MissingParameterException,
1551 			OperationFailedException, PermissionDeniedException {
1552 		// Check Missing params
1553 		checkForMissingParameter(cluId, "cluId");
1554 		checkForMissingParameter(luState, "luState");
1555 		Clu clu = luDao.fetch(Clu.class, cluId);
1556 		clu.setState(luState);
1557 		Clu updated = luDao.update(clu);
1558 		return LuServiceAssembler.toCluInfo(updated);
1559 	}
1560 
1561 	@Override
1562 	public List<ValidationResultInfo> validateCluCluRelation(
1563 			String validationType, CluCluRelationInfo cluCluRelationInfo)
1564 			throws DoesNotExistException, InvalidParameterException,
1565 			MissingParameterException, OperationFailedException {
1566 		checkForMissingParameter(validationType, "validationType");
1567 		checkForMissingParameter(cluCluRelationInfo, "cluCluRelationInfo");
1568 
1569         ObjectStructureDefinition objStructure = this.getObjectStructure(CluCluRelationInfo.class.getName());
1570         Validator defaultValidator = validatorFactory.getValidator();
1571         List<ValidationResultInfo> validationResults = defaultValidator.validateObject(cluCluRelationInfo, objStructure);
1572         
1573         return validationResults;
1574 	}
1575 
1576 	@Override
1577 	@Transactional(readOnly=false)
1578 	public CluCluRelationInfo createCluCluRelation(String cluId,
1579 			String relatedCluId, String luLuRelationTypeKey,
1580 			CluCluRelationInfo cluCluRelationInfo)
1581 			throws AlreadyExistsException, DataValidationErrorException,
1582 			DoesNotExistException, InvalidParameterException,
1583 			MissingParameterException, OperationFailedException,
1584 			PermissionDeniedException, CircularRelationshipException {
1585 		checkForMissingParameter(cluId, "cluId");
1586 		checkForMissingParameter(relatedCluId, "relatedCluId");
1587 		checkForMissingParameter(luLuRelationTypeKey, "luLuRelationTypeKey");
1588 		checkForMissingParameter(cluCluRelationInfo, "cluCluRelationInfo");
1589 
1590 		if (cluId.equals(relatedCluId)) {
1591 			throw new CircularRelationshipException(
1592 					"Can not relate a Clu to itself");
1593 		}
1594 
1595 		// Validate CluCluRelationInfo
1596 		List<ValidationResultInfo> val = validateCluCluRelation("SYSTEM", cluCluRelationInfo);
1597 		if(null != val && val.size() > 0) {
1598 			throw new DataValidationErrorException("Validation error!", val);
1599 		}
1600 
1601 
1602 		Clu clu = luDao.fetch(Clu.class, cluId);
1603 		Clu relatedClu = luDao.fetch(Clu.class, relatedCluId);
1604 
1605 		CluCluRelation cluCluRelation = new CluCluRelation();
1606 		BeanUtils.copyProperties(cluCluRelationInfo, cluCluRelation,
1607 				new String[] { "cluId", "relatedCluId",
1608 						"isCluRelationRequired", "attributes", "metaInfo" });
1609 
1610 		cluCluRelation.setClu(clu);
1611 		cluCluRelation.setRelatedClu(relatedClu);
1612 		cluCluRelation.setCluRelationRequired(cluCluRelationInfo
1613 				.getIsCluRelationRequired() == null ? true : cluCluRelationInfo
1614 				.getIsCluRelationRequired()); // TODO maybe this is unnecessary,
1615 		// contract specifies not null
1616 		cluCluRelation.setAttributes(LuServiceAssembler.toGenericAttributes(
1617 				CluCluRelationAttribute.class, cluCluRelationInfo
1618 						.getAttributes(), cluCluRelation, luDao));
1619 
1620 		LuLuRelationType luLuRelationType = luDao.fetch(LuLuRelationType.class,
1621 				luLuRelationTypeKey);
1622 
1623 		cluCluRelation.setLuLuRelationType(luLuRelationType);
1624 
1625 		luDao.create(cluCluRelation);
1626 
1627 		return LuServiceAssembler.toCluCluRelationInfo(cluCluRelation);
1628 	}
1629 
1630 	@Override
1631 	@Transactional(readOnly=false)
1632 	public CluCluRelationInfo updateCluCluRelation(
1633 			final String cluCluRelationId,
1634 			final CluCluRelationInfo cluCluRelationInfo)
1635 			throws DataValidationErrorException, DoesNotExistException,
1636 			InvalidParameterException, MissingParameterException,
1637 			OperationFailedException, PermissionDeniedException,
1638 			VersionMismatchException {
1639 		checkForMissingParameter(cluCluRelationId, "cluCluRelationId");
1640 		checkForMissingParameter(cluCluRelationInfo, "cluCluRelationInfo");
1641 
1642 		// Validate CluCluRelationInfo
1643 		List<ValidationResultInfo> val = validateCluCluRelation("SYSTEM", cluCluRelationInfo);
1644 		if(null != val && val.size() > 0) {
1645 			throw new DataValidationErrorException("Validation error!", val);
1646 		}
1647 
1648 		final CluCluRelation cluCluRelation = luDao.fetch(CluCluRelation.class,
1649 				cluCluRelationId);
1650 		BeanUtils.copyProperties(cluCluRelationInfo, cluCluRelation,
1651 				new String[] { "cluId", "relatedCluId",
1652 						"isCluRelationRequired", "attributes", "metaInfo" });
1653 
1654 		cluCluRelation.setClu(luDao.fetch(Clu.class, cluCluRelationInfo
1655 				.getCluId()));
1656 		cluCluRelation.setRelatedClu(luDao.fetch(Clu.class, cluCluRelationInfo
1657 				.getRelatedCluId()));
1658 		cluCluRelation.setCluRelationRequired(cluCluRelationInfo
1659 				.getIsCluRelationRequired() == null ? true : cluCluRelationInfo
1660 				.getIsCluRelationRequired()); // TODO maybe this is unnecessary,
1661 		// contract specifies not null
1662 		cluCluRelation.setAttributes(LuServiceAssembler.toGenericAttributes(
1663 				CluCluRelationAttribute.class, cluCluRelationInfo
1664 						.getAttributes(), cluCluRelation, luDao));
1665 
1666 		cluCluRelation.setLuLuRelationType(luDao.fetch(LuLuRelationType.class,
1667 				cluCluRelationInfo.getType()));
1668 
1669 		final CluCluRelation update = luDao.update(cluCluRelation);
1670 
1671 		return LuServiceAssembler.toCluCluRelationInfo(update);
1672 	}
1673 
1674 	@Override
1675 	@Transactional(readOnly=false)
1676 	public StatusInfo deleteCluCluRelation(String cluCluRelationId)
1677 			throws DoesNotExistException, InvalidParameterException,
1678 			MissingParameterException, OperationFailedException,
1679 			PermissionDeniedException {
1680 		checkForMissingParameter(cluCluRelationId, "cluCluRelationId");
1681 
1682 		luDao.delete(CluCluRelation.class, cluCluRelationId);
1683 
1684 		StatusInfo statusInfo = new StatusInfo();
1685 		statusInfo.setSuccess(true);
1686 
1687 		return statusInfo;
1688 	}
1689 
1690 	@Override
1691 	public List<ValidationResultInfo> validateCluPublication(
1692 			String validationType, CluPublicationInfo cluPublicationInfo)
1693 			throws DoesNotExistException, InvalidParameterException,
1694 			MissingParameterException, OperationFailedException {
1695 
1696 		checkForMissingParameter(validationType, "validationType");
1697 		checkForMissingParameter(cluPublicationInfo, "cluPublicationInfo");
1698 		
1699         ObjectStructureDefinition objStructure = this.getObjectStructure(CluPublicationInfo.class.getName());
1700         Validator defaultValidator = validatorFactory.getValidator();
1701         List<ValidationResultInfo> validationResults = defaultValidator.validateObject(cluPublicationInfo, objStructure);
1702         return validationResults;
1703 	}
1704 
1705 	@Override
1706 	@Transactional(readOnly=false)
1707 	public CluPublicationInfo createCluPublication(String cluId,
1708 			String luPublicationType, CluPublicationInfo cluPublicationInfo)
1709 			throws AlreadyExistsException, DataValidationErrorException,
1710 			InvalidParameterException, MissingParameterException,
1711 			OperationFailedException, PermissionDeniedException {
1712 		checkForMissingParameter(cluId, "cluId");
1713 		checkForMissingParameter(luPublicationType, "luPublicationType");
1714 		checkForMissingParameter(cluPublicationInfo, "cluPublicationInfo");
1715 		
1716 		// Validate CLU
1717 		List<ValidationResultInfo> val;
1718 		try {
1719 			val = validateCluPublication("SYSTEM", cluPublicationInfo);
1720 			if(null != val && val.size() > 0) {
1721 				throw new DataValidationErrorException("Validation error!", val);
1722 			}
1723 		} catch (DoesNotExistException e) {
1724 			throw new OperationFailedException("Error creating clu",e);
1725 		}
1726 
1727 		
1728 		CluPublication cluPub = new CluPublication();
1729 		Clu clu;
1730 		try {
1731 			clu = luDao.fetch(Clu.class, cluId);
1732 		} catch (DoesNotExistException e) {
1733 			throw new InvalidParameterException("Clu does not exist for id:"+cluId);
1734 		}
1735 		
1736 		CluPublicationType type;
1737 		try{
1738 			type = luDao.fetch(CluPublicationType.class, luPublicationType);
1739 		} catch (DoesNotExistException e) {
1740 			throw new InvalidParameterException("CluPublication Type does not exist for id:" + luPublicationType);
1741 		}
1742 		
1743 		cluPub.setClu(clu);
1744 		cluPub.setId(cluPublicationInfo.getId());
1745 		cluPub.setEndCycle(cluPublicationInfo.getEndCycle());
1746 		cluPub.setStartCycle(cluPublicationInfo.getStartCycle());
1747 		cluPub.setEffectiveDate(cluPublicationInfo.getEffectiveDate());
1748 		cluPub.setExpirationDate(cluPublicationInfo.getExpirationDate());
1749 		cluPub.setState(cluPublicationInfo.getState());
1750 		cluPub.setType(type);
1751 		cluPub.setAttributes(LuServiceAssembler.toGenericAttributes(CluPublicationAttribute.class, cluPublicationInfo.getAttributes(), cluPub, luDao));
1752 		cluPub.setVariants(LuServiceAssembler.toCluPublicationVariants(cluPublicationInfo.getVariants(), cluPub, luDao));
1753 
1754         luDao.create(cluPub);
1755 
1756 		return LuServiceAssembler.toCluPublicationInfo(cluPub);
1757 	}
1758 
1759 	@Override
1760 	@Transactional(readOnly=false)
1761 	public CluPublicationInfo updateCluPublication(String cluPublicationId,
1762 			CluPublicationInfo cluPublicationInfo)
1763 			throws DataValidationErrorException, DoesNotExistException,
1764 			InvalidParameterException, MissingParameterException,
1765 			OperationFailedException, PermissionDeniedException,
1766 			VersionMismatchException {
1767 		checkForMissingParameter(cluPublicationId, "cluPublicationId");
1768 		checkForMissingParameter(cluPublicationInfo, "cluPublicationInfo");
1769 		
1770 		// Validate CLU
1771 		List<ValidationResultInfo> val;
1772 		try {
1773 			val = validateCluPublication("SYSTEM", cluPublicationInfo);
1774 			if(null != val && val.size() > 0) {
1775 				throw new DataValidationErrorException("Validation error!", val);
1776 			}
1777 		} catch (DoesNotExistException e) {
1778 			throw new OperationFailedException("Error creating clu",e);
1779 		}
1780 		
1781 		CluPublication cluPub = luDao.fetch(CluPublication.class, cluPublicationId);
1782 		
1783 		if (!String.valueOf(cluPub.getVersionNumber()).equals(
1784 				cluPublicationInfo.getMetaInfo().getVersionInd())) {
1785 			throw new VersionMismatchException(
1786 					"CluPublication to be updated is not the current version");
1787 		}
1788 		
1789 		Clu clu;
1790 		try {
1791 			clu = luDao.fetch(Clu.class, cluPublicationInfo.getCluId());
1792 		} catch (DoesNotExistException e) {
1793 			throw new InvalidParameterException("Clu does not exist for id:"+cluPublicationInfo.getCluId());
1794 		}
1795 		
1796 		CluPublicationType type;
1797 		try{
1798 			type = luDao.fetch(CluPublicationType.class, cluPublicationInfo.getType());
1799 		} catch (DoesNotExistException e) {
1800 			throw new InvalidParameterException("CluPublication Type does not exist for id:" + cluPublicationInfo.getType());
1801 		}
1802 
1803         // Update the list of variants
1804         // Get a map of Id->object of all the currently persisted objects in the
1805         // list
1806         Map<String, CluPublicationVariant> oldVariantMap = new HashMap<String, CluPublicationVariant>();
1807         for (CluPublicationVariant variant : cluPub.getVariants()) {
1808             oldVariantMap.put(variant.getKey(), variant);
1809         }
1810         cluPub.getVariants().clear();
1811 
1812         // Loop through the new list, if the item exists already update and
1813         // remove from the list otherwise create a new entry
1814         CluPublicationVariant variant = null;
1815         for (FieldInfo fieldInfo : cluPublicationInfo.getVariants()) {
1816             if (!oldVariantMap.containsKey(fieldInfo.getId())) {
1817                 // New variant key
1818                 variant = new CluPublicationVariant();
1819                 variant.setKey(fieldInfo.getId());
1820                 variant.setValue(fieldInfo.getValue());
1821             } else {
1822                 // Update existing variant
1823                 variant = oldVariantMap.get(fieldInfo.getId());
1824                 variant.setValue(fieldInfo.getValue());
1825                 oldVariantMap.remove(fieldInfo.getId());
1826             }
1827 
1828             cluPub.getVariants().add(variant);
1829         }
1830 
1831         // Now delete anything left over
1832         for (Entry<String, CluPublicationVariant> entry : oldVariantMap.entrySet()) {
1833             luDao.delete(entry.getValue());
1834         }
1835        
1836 		cluPub.setClu(clu);
1837 		cluPub.setEndCycle(cluPublicationInfo.getEndCycle());
1838 		cluPub.setStartCycle(cluPublicationInfo.getStartCycle());
1839 		cluPub.setEffectiveDate(cluPublicationInfo.getEffectiveDate());
1840 		cluPub.setExpirationDate(cluPublicationInfo.getExpirationDate());
1841 		cluPub.setState(cluPublicationInfo.getState());
1842 		cluPub.setType(type);
1843 		cluPub.setAttributes(LuServiceAssembler.toGenericAttributes(CluPublicationAttribute.class, cluPublicationInfo.getAttributes(), cluPub, luDao));
1844 
1845         CluPublication updated = luDao.update(cluPub);
1846 
1847 		return LuServiceAssembler.toCluPublicationInfo(updated);
1848 	}
1849 
1850 	@Override
1851 	@Transactional(readOnly=false)
1852 	public StatusInfo deleteCluPublication(String cluPublicationId)
1853 			throws DoesNotExistException, InvalidParameterException,
1854 			MissingParameterException, DependentObjectsExistException,
1855 			OperationFailedException, PermissionDeniedException {
1856 		checkForMissingParameter(cluPublicationId, "cluPublicationId");
1857 
1858 		luDao.delete(CluPublication.class, cluPublicationId);
1859 
1860 		StatusInfo statusInfo = new StatusInfo();
1861 		statusInfo.setSuccess(true);
1862 
1863 		return statusInfo;	}
1864 
1865 	@Override
1866 	public List<ValidationResultInfo> validateCluResult(String validationType,
1867 			CluResultInfo cluResultInfo) throws DoesNotExistException,
1868 			InvalidParameterException, MissingParameterException,
1869 			OperationFailedException {
1870 		checkForMissingParameter(validationType, "validationType");
1871 		checkForMissingParameter(cluResultInfo, "cluResultInfo");
1872 
1873         ObjectStructureDefinition objStructure = this.getObjectStructure(CluResultInfo.class.getName());
1874         Validator defaultValidator = validatorFactory.getValidator();
1875         List<ValidationResultInfo> validationResults = defaultValidator.validateObject(cluResultInfo, objStructure);
1876         return validationResults;
1877 	}
1878 
1879 	@Override
1880 	@Transactional(readOnly=false)
1881 	public CluResultInfo createCluResult(String cluId, String cluResultTypeKey,
1882 			CluResultInfo cluResultInfo) throws AlreadyExistsException,
1883 			DataValidationErrorException, InvalidParameterException,
1884 			MissingParameterException, OperationFailedException,
1885 			PermissionDeniedException, DoesNotExistException {
1886 
1887 		checkForMissingParameter(cluId, "cluId");
1888 		checkForMissingParameter(cluResultTypeKey, "cluResultTypeKey");
1889 		checkForMissingParameter(cluResultInfo, "cluResultInfo");
1890 
1891 		// Validate CluResult
1892 		List<ValidationResultInfo> val = validateCluResult("SYSTEM", cluResultInfo);
1893 		if(null != val && val.size() > 0) {
1894 			throw new DataValidationErrorException("Validation error!", val);
1895 		}
1896 
1897 		cluResultInfo.setType(cluResultTypeKey);
1898 		cluResultInfo.setCluId(cluId);
1899 
1900 		List<ResultOption> resOptList = new ArrayList<ResultOption>();
1901 		for (ResultOptionInfo resOptInfo : cluResultInfo.getResultOptions()) {
1902 			ResultOption resOpt = new ResultOption();
1903 			BeanUtils.copyProperties(resOptInfo, resOpt, new String[] { "id",
1904 					"metaInfo", "resultUsageType", "desc" });
1905 
1906 			if(resOptInfo.getResultUsageTypeKey() != null) {
1907 				ResultUsageType resUsageType = luDao.fetch(ResultUsageType.class,
1908 						resOptInfo.getResultUsageTypeKey());
1909 				resOpt.setResultUsageType(resUsageType);
1910 			}
1911 			resOpt.setDesc(LuServiceAssembler.toRichText(LuRichText.class, resOptInfo.getDesc()));
1912 			luDao.create(resOpt);
1913 			resOptList.add(resOpt);
1914 		}
1915 
1916 		CluResult cluResult = new CluResult();
1917 		BeanUtils.copyProperties(cluResultInfo, cluResult, new String[] { "id",
1918 				"desc", "resultOptions", "metaInfo" });
1919 
1920 		cluResult.setDesc(LuServiceAssembler
1921 				.toRichText(LuRichText.class, cluResultInfo.getDesc()));
1922 		cluResult.setResultOptions(resOptList);
1923 
1924 		Clu clu = luDao.fetch(Clu.class, cluId);
1925 		cluResult.setClu(clu);
1926 
1927 		CluResultType type = luDao.fetch(CluResultType.class, cluResultTypeKey);
1928 		cluResult.setCluResultType(type);
1929 
1930 		luDao.create(cluResult);
1931 
1932 		return LuServiceAssembler.toCluResultInfo(cluResult);
1933 	}
1934 
1935 	@Override
1936 	@Transactional(readOnly=false)
1937 	public CluResultInfo updateCluResult(String cluResultId,
1938 			CluResultInfo cluResultInfo) throws DataValidationErrorException,
1939 			DoesNotExistException, InvalidParameterException,
1940 			MissingParameterException, OperationFailedException,
1941 			PermissionDeniedException, VersionMismatchException {
1942 
1943 		checkForMissingParameter(cluResultId, "cluResultId");
1944 		checkForMissingParameter(cluResultInfo, "cluResultInfo");
1945 
1946 		// Validate CluResult
1947 		List<ValidationResultInfo> val = validateCluResult("SYSTEM", cluResultInfo);
1948 		if(null != val && val.size() > 0) {
1949 			throw new DataValidationErrorException("Validation error!", val);
1950 		}
1951 
1952 		CluResult result = luDao.fetch(CluResult.class, cluResultId);
1953 		if (!String.valueOf(result.getVersionNumber()).equals(
1954 				cluResultInfo.getMetaInfo().getVersionInd())) {
1955 			throw new VersionMismatchException(
1956 					"CluResult to be updated is not the current version");
1957 		}
1958 
1959 		// Update the list of resultoptions
1960 		// Get a map of Id->object of all the currently persisted objects in the
1961 		// list
1962 		Map<String, ResultOption> oldResultOptionMap = new HashMap<String, ResultOption>();
1963 		for (ResultOption opt : result.getResultOptions()) {
1964 			oldResultOptionMap.put(opt.getId(), opt);
1965 		}
1966 		result.getResultOptions().clear();
1967 
1968 		// Loop through the new list, if the item exists already update and
1969 		// remove from the list otherwise create a new entry
1970 		for (ResultOptionInfo resOptInfo : cluResultInfo.getResultOptions()) {
1971 			ResultOption opt = oldResultOptionMap.remove(resOptInfo.getId());
1972 			if (opt == null) {
1973 				// New result option
1974 				opt = new ResultOption();
1975 				// Copy properties
1976 				BeanUtils.copyProperties(resOptInfo, opt, new String[] {
1977 						"resultUsageType", "desc" });
1978 			} else {
1979 				// Get existing result option
1980 				opt = luDao.fetch(ResultOption.class, resOptInfo.getId());
1981 				// Copy properties
1982 				BeanUtils.copyProperties(resOptInfo, opt, new String[] {
1983 						"id", "resultUsageType", "desc" });
1984 			}
1985 			if(resOptInfo.getResultUsageTypeKey() != null && !resOptInfo.getResultUsageTypeKey().isEmpty()) {
1986 				ResultUsageType resUsageType = luDao.fetch(ResultUsageType.class,
1987 						resOptInfo.getResultUsageTypeKey());
1988 				opt.setResultUsageType(resUsageType);
1989 			}
1990 			opt.setDesc(LuServiceAssembler.toRichText(LuRichText.class, resOptInfo.getDesc()));
1991 			result.getResultOptions().add(opt);
1992 		}
1993 
1994 		// Now delete anything left over
1995 		for (Entry<String, ResultOption> entry : oldResultOptionMap.entrySet()) {
1996 			luDao.delete(entry.getValue());
1997 		}
1998 
1999 		BeanUtils.copyProperties(cluResultInfo, result, new String[] { "id",
2000 				"desc", "resultOptions" });
2001 
2002 		result.setDesc(LuServiceAssembler.toRichText(LuRichText.class, cluResultInfo.getDesc()));
2003 		CluResultType type = luDao.fetch(CluResultType.class, cluResultInfo.getType());
2004 		result.setCluResultType(type);
2005 
2006 		CluResult updated = luDao.update(result);
2007 
2008 		return LuServiceAssembler.toCluResultInfo(updated);
2009 	}
2010 
2011 	@Override
2012 	@Transactional(readOnly=false)
2013 	public StatusInfo deleteCluResult(String cluResultId)
2014 			throws DoesNotExistException, InvalidParameterException,
2015 			MissingParameterException, DependentObjectsExistException,
2016 			OperationFailedException, PermissionDeniedException {
2017 
2018 		checkForMissingParameter(cluResultId, "cluResultId");
2019 
2020 		luDao.delete(CluResult.class, cluResultId);
2021 
2022 		StatusInfo statusInfo = new StatusInfo();
2023 		statusInfo.setSuccess(true);
2024 
2025 		return statusInfo;
2026 	}
2027 
2028 	@Override
2029 	public List<ValidationResultInfo> validateCluLoRelation(
2030 			String validationType, CluLoRelationInfo cluLoRelationInfo)
2031 			throws DoesNotExistException, InvalidParameterException,
2032 			MissingParameterException, OperationFailedException {
2033 
2034 		checkForMissingParameter(validationType, "validationType");
2035 		checkForMissingParameter(cluLoRelationInfo, "cluLoRelationInfo");
2036 
2037         ObjectStructureDefinition objStructure = this.getObjectStructure(CluLoRelation.class.getName());
2038         Validator defaultValidator = validatorFactory.getValidator();
2039         List<ValidationResultInfo> validationResults = defaultValidator.validateObject(cluLoRelationInfo, objStructure);
2040         return validationResults;
2041 	}
2042 
2043 	@Override
2044 	@Transactional(readOnly=false)
2045 	public CluLoRelationInfo createCluLoRelation(String cluId, String loId,
2046 			String cluLoRelationType, CluLoRelationInfo cluLoRelationInfo)
2047 			throws AlreadyExistsException, DoesNotExistException,
2048 			InvalidParameterException, MissingParameterException,
2049 			OperationFailedException, PermissionDeniedException, DataValidationErrorException {
2050 		checkForMissingParameter(loId, "loId");
2051 		checkForMissingParameter(cluId, "cluId");
2052 		checkForEmptyList(cluLoRelationType, "cluLoRelationType");
2053 		checkForEmptyList(cluLoRelationInfo, "cluLoRelationInfo");
2054 
2055 		// Validate CluLoRelation
2056 		List<ValidationResultInfo> val = validateCluLoRelation("SYSTEM", cluLoRelationInfo);
2057 		if(null != val && val.size() > 0) {
2058 			throw new DataValidationErrorException("Validation error!", val);
2059 		}
2060 
2061 		Clu clu = luDao.fetch(Clu.class, cluId);
2062 		if (clu == null) {
2063 			throw new DoesNotExistException("Clu does not exist for id: "
2064 					+ cluId);
2065 		}
2066 		
2067 		CluLoRelationType cluLoRelationTypeEntity = luDao.fetch(CluLoRelationType.class, cluLoRelationType);
2068 		if (cluLoRelationTypeEntity == null) {
2069 			throw new DoesNotExistException("CluLoRelationType does not exist for id: "
2070 					+ cluLoRelationType);
2071 		}
2072 
2073 		// Check to see if this relation already exists
2074 		List<CluLoRelation> reltns = luDao.getCluLoRelationsByCludIdAndLoId(
2075 				cluId, loId);
2076 		if (reltns.size() > 0) {
2077 			throw new AlreadyExistsException(
2078 					"Relation already exists for cluId:" + cluId + " and Lo:"
2079 							+ loId);
2080 		}
2081 
2082 		CluLoRelation cluLoRelation = new CluLoRelation();
2083 		BeanUtils.copyProperties(cluLoRelationInfo, cluLoRelation,
2084 				new String[] { "cluId", "attributes", "metaInfo", "type" });
2085 
2086 		cluLoRelation.setClu(clu);
2087 		cluLoRelation.setAttributes(LuServiceAssembler.toGenericAttributes(
2088 				CluLoRelationAttribute.class,
2089 				cluLoRelationInfo.getAttributes(), cluLoRelation, luDao));
2090 		cluLoRelation.setType(cluLoRelationTypeEntity);
2091 		
2092 		luDao.create(cluLoRelation);
2093 
2094 		return LuServiceAssembler.toCluLoRelationInfo(cluLoRelation);
2095 	}
2096 
2097 	@Override
2098 	@Transactional(readOnly=false)
2099 	public CluLoRelationInfo updateCluLoRelation(String cluLoRelationId,
2100 			CluLoRelationInfo cluLoRelationInfo)
2101 			throws DataValidationErrorException, DoesNotExistException,
2102 			InvalidParameterException, MissingParameterException,
2103 			OperationFailedException, PermissionDeniedException,
2104 			VersionMismatchException {
2105 		checkForMissingParameter(cluLoRelationId, "cluLoRelationId");
2106 		checkForMissingParameter(cluLoRelationInfo, "cluLoRelationInfo");
2107 
2108 		// Validate CluLoRelation
2109 		List<ValidationResultInfo> val = validateCluLoRelation("SYSTEM", cluLoRelationInfo);
2110 		if(null != val && val.size() > 0) {
2111 			throw new DataValidationErrorException("Validation error!", val);
2112 		}
2113 
2114 		CluLoRelation reltn = luDao.fetch(CluLoRelation.class, cluLoRelationId);
2115 
2116 		if (!String.valueOf(reltn.getVersionNumber()).equals(
2117 				cluLoRelationInfo.getMetaInfo().getVersionInd())) {
2118 			throw new VersionMismatchException(
2119 					"CluLoRelation to be updated is not the current version");
2120 		}
2121 
2122 		Clu clu = luDao.fetch(Clu.class, cluLoRelationInfo.getCluId());
2123 		if (clu == null) {
2124 			throw new DoesNotExistException("Clu does not exist for id: "
2125 					+ cluLoRelationInfo.getCluId());
2126 		}
2127 
2128 		CluLoRelationType cluLoRelationTypeEntity = luDao.fetch(CluLoRelationType.class, cluLoRelationInfo.getType());
2129 		if (cluLoRelationTypeEntity == null) {
2130 			throw new DoesNotExistException("CluLoRelationType does not exist for id: "
2131 					+ cluLoRelationInfo.getType());
2132 		}
2133 		
2134 		BeanUtils.copyProperties(cluLoRelationInfo, reltn, new String[] {
2135 				"cluId", "attributes", "metaInfo", "type"});
2136 
2137 		reltn.setClu(clu);
2138 		reltn.setAttributes(LuServiceAssembler.toGenericAttributes(
2139 				CluLoRelationAttribute.class,
2140 				cluLoRelationInfo.getAttributes(), reltn, luDao));
2141 		reltn.setType(cluLoRelationTypeEntity);
2142 		CluLoRelation updated = luDao.update(reltn);
2143 
2144 		return LuServiceAssembler.toCluLoRelationInfo(updated);
2145 	}
2146 
2147 	@Override
2148 	@Transactional(readOnly=false)
2149 	public StatusInfo deleteCluLoRelation(String cluLoRelationId)
2150 			throws DoesNotExistException, InvalidParameterException,
2151 			MissingParameterException, OperationFailedException,
2152 			PermissionDeniedException {
2153 		checkForMissingParameter(cluLoRelationId, "cluLoRelationId");
2154 
2155 		CluLoRelation reltn = luDao.fetch(CluLoRelation.class, cluLoRelationId);
2156 		if (reltn == null) {
2157 			throw new DoesNotExistException(
2158 					"CluLoRelation does not exist for id: " + cluLoRelationId);
2159 		}
2160 
2161 		luDao.delete(CluLoRelation.class, cluLoRelationId);
2162 
2163 		StatusInfo statusInfo = new StatusInfo();
2164 		statusInfo.setSuccess(true);
2165 
2166 		return statusInfo;
2167 	}
2168 
2169 	@Override
2170 	@Transactional(readOnly=false)
2171 	public StatusInfo addCluResourceRequirement(String resourceTypeKey,
2172 			String cluId) throws AlreadyExistsException, DoesNotExistException,
2173 			InvalidParameterException, MissingParameterException,
2174 			OperationFailedException, PermissionDeniedException {
2175 	      throw new UnsupportedOperationException("Method not yet implemented!");
2176 	}
2177 
2178 	@Override
2179 	@Transactional(readOnly=false)
2180 	public StatusInfo removeCluResourceRequirement(String resourceTypeKey,
2181 			String cluId) throws DoesNotExistException,
2182 			InvalidParameterException, MissingParameterException,
2183 			OperationFailedException, PermissionDeniedException {
2184 		// TODO Auto-generated method stub
2185 		return null;
2186 	}
2187 
2188 	@Override
2189 	public List<ValidationResultInfo> validateCluSet(String validationType,
2190 			CluSetInfo cluSetInfo) throws DoesNotExistException,
2191 			InvalidParameterException, MissingParameterException,
2192 			OperationFailedException {
2193 		checkForMissingParameter(validationType, "validationType");
2194 		checkForMissingParameter(cluSetInfo, "cluSetInfo");
2195 
2196         ObjectStructureDefinition objStructure = this.getObjectStructure(CluSetInfo.class.getName());
2197         Validator defaultValidator = validatorFactory.getValidator();
2198         List<ValidationResultInfo> validationResults = defaultValidator.validateObject(cluSetInfo, objStructure);
2199         return validationResults;
2200 	}
2201 
2202 	@Override
2203 	@Transactional(readOnly=false)
2204 	public CluSetInfo createCluSet(String cluSetType, CluSetInfo cluSetInfo)
2205 			throws AlreadyExistsException, DataValidationErrorException,
2206 			InvalidParameterException, MissingParameterException,
2207 			OperationFailedException, PermissionDeniedException,
2208 			UnsupportedActionException {
2209 
2210 		checkForMissingParameter(cluSetType, "cluSetType");
2211 		checkForMissingParameter(cluSetInfo, "cluSetInfo");
2212 
2213 		cluSetInfo.setType(cluSetType);
2214 
2215 		validateCluSet(cluSetInfo);
2216 
2217 		// Validate CluSet
2218 		List<ValidationResultInfo> val;
2219 		try {
2220 			val = validateCluSet("SYSTEM", cluSetInfo);
2221 		} catch (DoesNotExistException e) {
2222 			throw new DataValidationErrorException("Validation error! " + e.getMessage());
2223 		}
2224 		if(null != val && val.size() > 0) {
2225 			throw new DataValidationErrorException("Validation error!", val);
2226 		}
2227 
2228 		List<String> cluIdList = getMembershipQuerySearchResult(cluSetInfo.getMembershipQuery());
2229 
2230 		CluSet cluSet = null;
2231 		try {
2232 			cluSet = LuServiceAssembler.toCluSetEntity(cluSetInfo, this.luDao);
2233 		} catch (DoesNotExistException e) {
2234 			throw new DataValidationErrorException("Creating CluSet entity failed. Clu or CluSet does not exist: " + e.getMessage());
2235 		}
2236 
2237 		cluSet = luDao.create(cluSet);
2238 
2239 		CluSetInfo newCluSetInfo = LuServiceAssembler.toCluSetInfo(cluSet);
2240 
2241 		if(cluIdList != null) {
2242 			newCluSetInfo.getCluIds().addAll(cluIdList);
2243 		}
2244 
2245 		return newCluSetInfo;
2246 	}
2247 
2248 	private void setMembershipQuerySearchResult(CluSetInfo cluSetInfo) throws MissingParameterException {
2249 		if(cluSetInfo.getMembershipQuery() == null) {
2250 			return;
2251 		}
2252 		List<String> cluIds = getMembershipQuerySearchResult(cluSetInfo.getMembershipQuery());
2253 		cluSetInfo.getCluIds().addAll(cluIds);
2254 	}
2255 
2256 	private List<String> getMembershipQuerySearchResult(MembershipQueryInfo query) throws MissingParameterException {
2257 		if(query == null) {
2258 			return null;
2259 		}
2260 		SearchRequest sr = new SearchRequest();
2261 		sr.setSearchKey(query.getSearchTypeKey());
2262 		sr.setParams(query.getQueryParamValueList());
2263 
2264 		SearchResult result = search(sr);
2265 
2266 		Set<String> cluIds = new HashSet<String>();
2267 		List<SearchResultRow> rows = result.getRows();
2268 		for(SearchResultRow row : rows) {
2269 			List<SearchResultCell> cells = row.getCells();
2270 			for(SearchResultCell cell : cells) {
2271 				if(cell.getKey().equals("lu.resultColumn.luOptionalVersionIndId")&&cell.getValue()!=null) {
2272 					cluIds.add(cell.getValue());
2273 				}
2274 			}
2275 		}
2276 		return new ArrayList<String>(cluIds);
2277 	}
2278 
2279 	private void validateCluSet(CluSetInfo cluSetInfo) throws UnsupportedActionException {
2280 		MembershipQueryInfo mqInfo = cluSetInfo.getMembershipQuery();
2281 
2282 		if (cluSetInfo.getType() == null) {
2283 			throw new UnsupportedActionException("CluSet type cannot be null. CluSet id="+cluSetInfo.getId());
2284 		}
2285 		else if(mqInfo != null && mqInfo.getSearchTypeKey() != null && !mqInfo.getSearchTypeKey().isEmpty() &&
2286 				(cluSetInfo.getCluIds().size() > 0 || cluSetInfo.getCluSetIds().size() > 0)) {
2287 			throw new UnsupportedActionException("Dynamic CluSet cannot contain Clus and/or CluSets. CluSet id="+cluSetInfo.getId());
2288 		}
2289 		else if (cluSetInfo.getCluIds().size() > 0 && cluSetInfo.getCluSetIds().size() > 0) {
2290 			throw new UnsupportedActionException("CluSet cannot contain both Clus and CluSets. CluSet id="+cluSetInfo.getId());
2291 		}
2292 	}
2293 
2294 	@Override
2295 	@Transactional(readOnly=false)
2296 	public CluSetInfo updateCluSet(String cluSetId, CluSetInfo cluSetInfo)
2297 			throws DataValidationErrorException, DoesNotExistException,
2298 			InvalidParameterException, MissingParameterException,
2299 			OperationFailedException, PermissionDeniedException,
2300 			VersionMismatchException, CircularRelationshipException,
2301 			UnsupportedActionException {
2302 
2303 		// Check Missing params
2304 		checkForMissingParameter(cluSetId, "cluSetId");
2305 		checkForMissingParameter(cluSetInfo, "cluSetInfo");
2306 
2307 		// Validate CluSet
2308 		List<ValidationResultInfo> val = validateCluSet("SYSTEM", cluSetInfo);
2309 		if(null != val && val.size() > 0) {
2310 			throw new DataValidationErrorException("Validation error!", val);
2311 		}
2312 
2313 		cluSetInfo.setId(cluSetId);
2314 
2315 		validateCluSet(cluSetInfo);
2316 
2317 		List<String> cluIdList = getMembershipQuerySearchResult(cluSetInfo.getMembershipQuery());
2318 
2319 		CluSet cluSet = luDao.fetch(CluSet.class, cluSetId);
2320 
2321 		if (!cluSetInfo.getType().equals(cluSet.getType())) {
2322 			throw new UnsupportedActionException("CluSet type is set at creation time and cannot be updated. CluSet id="+cluSetId);
2323 		}
2324 
2325 		if (!String.valueOf(cluSet.getVersionNumber()).equals(
2326 				cluSetInfo.getMetaInfo().getVersionInd())) {
2327 			throw new VersionMismatchException(
2328 					"CluSet (id=" + cluSetId +
2329 					") to be updated is not the current version " +
2330 					"(version=" + cluSetInfo.getMetaInfo().getVersionInd() +
2331 					"), current version="+cluSet.getVersionNumber());
2332 		}
2333 
2334 		// update the cluIds
2335 		Map<String, CluSetJoinVersionIndClu> oldClus = new HashMap<String, CluSetJoinVersionIndClu>();
2336 		for(CluSetJoinVersionIndClu join:cluSet.getCluVerIndIds()){
2337 			oldClus.put(join.getCluVersionIndId(), join);
2338 		}
2339 
2340 		cluSet.getCluVerIndIds().clear();
2341 		// Loop through the new list, if the item exists already update and remove from the list otherwise create a new entry
2342 		for (String newCluId : cluSetInfo.getCluIds()) {
2343 			CluSetJoinVersionIndClu join = oldClus.remove(newCluId);
2344 			if (join == null) {
2345 				join = new CluSetJoinVersionIndClu();
2346 				join.setCluSet(cluSet);
2347 				join.setCluVersionIndId(newCluId);
2348 			}
2349 			cluSet.getCluVerIndIds().add(join);
2350 		}
2351 
2352 		// Now delete anything left over
2353 		for (Entry<String, CluSetJoinVersionIndClu> entry : oldClus.entrySet()) {
2354 			luDao.delete(entry.getValue());
2355 		}
2356 
2357         // clean up existing wrappers if any
2358         if (cluSetInfo.getId() != null) {
2359             CluSetInfo originalCluSet = getCluSetInfo(cluSetInfo.getId());
2360             List<CluSetInfo> origSubCSs = null;
2361             List<String> origSubCSIds = originalCluSet.getCluSetIds();
2362             if (origSubCSIds != null && !origSubCSIds.isEmpty()) {
2363                 origSubCSs = getCluSetInfoByIdList(origSubCSIds);
2364             }
2365             if (origSubCSs != null) {
2366                 for (CluSetInfo origSubCS : origSubCSs) {
2367                     if (!origSubCS.getIsReusable()) {
2368                         deleteCluSet(origSubCS.getId());
2369                     }
2370                 }
2371             }
2372         }
2373 
2374 		// update the cluSetIds
2375 		if(cluSet.getCluSets()==null){
2376 			cluSet.setCluSets(new ArrayList<CluSet>());
2377 		}
2378 		cluSet.setCluSets(null);
2379 		if(!cluSetInfo.getCluSetIds().isEmpty()) {
2380 			Set<String> newCluSetIds = new HashSet<String>(cluSetInfo.getCluSetIds());
2381 			if(cluSet.getCluSets()!=null){
2382 				for (Iterator<CluSet> i = cluSet.getCluSets().iterator(); i.hasNext();) {
2383 					if (!newCluSetIds.remove(i.next().getId())) {
2384 						i.remove();
2385 					}
2386 				}
2387 			}
2388 			List<CluSet> cluSetList = luDao.getCluSetInfoByIdList(new ArrayList<String>(newCluSetIds));
2389 			cluSet.setCluSets(cluSetList);
2390 		}
2391 
2392 		BeanUtils.copyProperties(cluSetInfo, cluSet, new String[] { "descr",
2393 				"attributes", "metaInfo", "membershipQuery" });
2394 		cluSet.setAttributes(LuServiceAssembler.toGenericAttributes(
2395 				CluSetAttribute.class, cluSetInfo.getAttributes(), cluSet, luDao));
2396 		cluSet.setDescr(LuServiceAssembler.toRichText(LuRichText.class, cluSetInfo.getDescr()));
2397 
2398 		MembershipQuery mq = LuServiceAssembler.toMembershipQueryEntity(cluSetInfo.getMembershipQuery());
2399 		cluSet.setMembershipQuery(mq);
2400 
2401 		CluSet updated = luDao.update(cluSet);
2402 
2403 		CluSetInfo updatedCluSetInfo = LuServiceAssembler.toCluSetInfo(updated);
2404 
2405 		if(cluIdList != null) {
2406 			updatedCluSetInfo.getCluIds().addAll(cluIdList);
2407 		}
2408 
2409 		return updatedCluSetInfo;
2410 	}
2411 
2412 	@Override
2413 	@Transactional(readOnly=false)
2414 	public StatusInfo deleteCluSet(String cluSetId)
2415 			throws DoesNotExistException, InvalidParameterException,
2416 			MissingParameterException, OperationFailedException,
2417 			PermissionDeniedException {
2418 
2419 		checkForMissingParameter(cluSetId, "cluSetId");
2420 
2421 		luDao.delete(CluSet.class, cluSetId);
2422 
2423 		StatusInfo statusInfo = new StatusInfo();
2424 		statusInfo.setSuccess(true);
2425 
2426 		return statusInfo;
2427 	}
2428 
2429 	@Override
2430 	@Transactional(readOnly=false)
2431 	public StatusInfo addCluSetToCluSet(String cluSetId, String addedCluSetId)
2432 			throws DoesNotExistException, InvalidParameterException,
2433 			MissingParameterException, OperationFailedException,
2434 			PermissionDeniedException, UnsupportedActionException,
2435 			CircularRelationshipException {
2436 		checkForMissingParameter(cluSetId, "cluSetId");
2437 		checkForMissingParameter(addedCluSetId, "addedCluSetId");
2438 
2439 		CluSet cluSet = luDao.fetch(CluSet.class, cluSetId);
2440 
2441 		checkCluSetAlreadyAdded(cluSet, addedCluSetId);
2442 
2443 		CluSet addedCluSet = luDao.fetch(CluSet.class, addedCluSetId);
2444 
2445 		checkCluSetCircularReference(addedCluSet, cluSetId);
2446 
2447 		if(cluSet.getCluSets()==null){
2448 			cluSet.setCluSets(new ArrayList<CluSet>());
2449 		}
2450 		cluSet.getCluSets().add(addedCluSet);
2451 
2452 		luDao.update(cluSet);
2453 
2454 		StatusInfo statusInfo = new StatusInfo();
2455 		statusInfo.setSuccess(true);
2456 
2457 		return statusInfo;
2458 	}
2459 
2460 	@Override
2461 	@Transactional(readOnly=false)
2462 	public StatusInfo removeCluSetFromCluSet(String cluSetId,
2463 			String removedCluSetId) throws DoesNotExistException,
2464 			InvalidParameterException, MissingParameterException,
2465 			OperationFailedException, PermissionDeniedException,
2466 			UnsupportedActionException {
2467 
2468 		checkForMissingParameter(cluSetId, "cluSetId");
2469 		checkForMissingParameter(removedCluSetId, "removedCluSetId");
2470 
2471 		CluSet cluSet = luDao.fetch(CluSet.class, cluSetId);
2472 		if(cluSet.getCluSets()!=null){
2473 			for (Iterator<CluSet> i = cluSet.getCluSets().iterator(); i.hasNext();) {
2474 				CluSet childCluSet = i.next();
2475 				if (childCluSet.getId().equals(removedCluSetId)) {
2476 					i.remove();
2477 					luDao.update(cluSet);
2478 					StatusInfo statusInfo = new StatusInfo();
2479 					statusInfo.setSuccess(true);
2480 	
2481 					return statusInfo;
2482 				}
2483 			}
2484 		}
2485 
2486 		StatusInfo statusInfo = new StatusInfo();
2487 		statusInfo.setSuccess(false);
2488 		statusInfo.setMessage("CluSet does not contain CluSet:"
2489 				+ removedCluSetId);
2490 
2491 		return statusInfo;
2492 	}
2493 
2494 	@Override
2495 	@Transactional(readOnly=false)
2496 	public StatusInfo addCluToCluSet(String cluId, String cluSetId)
2497 			throws DoesNotExistException, InvalidParameterException,
2498 			MissingParameterException, OperationFailedException,
2499 			PermissionDeniedException, UnsupportedActionException {
2500 
2501 		checkForMissingParameter(cluId, "cluId");
2502 		checkForMissingParameter(cluSetId, "cluSetId");
2503 
2504 		CluSet cluSet = luDao.fetch(CluSet.class, cluSetId);
2505 
2506 		checkCluAlreadyAdded(cluSet, cluId);
2507 		
2508 		try{
2509 			luDao.getCurrentCluVersionInfo(cluId, LuServiceConstants.CLU_NAMESPACE_URI);
2510 		}catch(NoResultException e){
2511 			throw new DoesNotExistException();
2512 		}
2513 		
2514 		CluSetJoinVersionIndClu join = new CluSetJoinVersionIndClu();
2515 		join.setCluSet(cluSet);
2516 		join.setCluVersionIndId(cluId);
2517 		
2518 		cluSet.getCluVerIndIds().add(join);
2519 
2520 		luDao.update(cluSet);
2521 
2522 		StatusInfo statusInfo = new StatusInfo();
2523 		statusInfo.setSuccess(true);
2524 
2525 		return statusInfo;
2526 	}
2527 
2528 	@Override
2529 	@Transactional(readOnly=false)
2530 	public StatusInfo removeCluFromCluSet(String cluId, String cluSetId)
2531 			throws DoesNotExistException, InvalidParameterException,
2532 			MissingParameterException, OperationFailedException,
2533 			PermissionDeniedException, UnsupportedActionException {
2534 
2535 		checkForMissingParameter(cluId, "cluId");
2536 		checkForMissingParameter(cluSetId, "cluSetId");
2537 
2538 		CluSet cluSet = luDao.fetch(CluSet.class, cluSetId);
2539 
2540 		for (Iterator<CluSetJoinVersionIndClu> i = cluSet.getCluVerIndIds().iterator(); i.hasNext();) {
2541 			CluSetJoinVersionIndClu join = i.next();
2542 			if (join.getCluVersionIndId().equals(cluId)) {
2543 				i.remove();
2544 				luDao.delete(join);
2545 				luDao.update(cluSet);
2546 				StatusInfo statusInfo = new StatusInfo();
2547 				statusInfo.setSuccess(true);
2548 
2549 				return statusInfo;
2550 			}
2551 		}
2552 
2553 		StatusInfo statusInfo = new StatusInfo();
2554 		statusInfo.setSuccess(false);
2555 		statusInfo.setMessage("Clu set does not contain Clu:" + cluId);
2556 
2557 		return statusInfo;
2558 	}
2559 
2560 	@Override
2561 	public List<ValidationResultInfo> validateLui(String validationType,
2562 			LuiInfo luiInfo) throws DoesNotExistException,
2563 			InvalidParameterException, MissingParameterException,
2564 			OperationFailedException {
2565 		checkForMissingParameter(validationType, "validationType");
2566 		checkForMissingParameter(luiInfo, "luiInfo");
2567 
2568         ObjectStructureDefinition objStructure = this.getObjectStructure(LuiInfo.class.getName());
2569         Validator defaultValidator = validatorFactory.getValidator();
2570         List<ValidationResultInfo> validationResults = defaultValidator.validateObject(luiInfo, objStructure);
2571         return validationResults;
2572 	}
2573 
2574 	@Override
2575 	@Transactional(readOnly=false)
2576 	public LuiInfo createLui(String cluId, String atpKey, LuiInfo luiInfo)
2577 			throws AlreadyExistsException, DataValidationErrorException,
2578 			DoesNotExistException, InvalidParameterException,
2579 			MissingParameterException, OperationFailedException,
2580 			PermissionDeniedException {
2581 		checkForMissingParameter(cluId, "cludId");
2582 		checkForMissingParameter(atpKey, "atpKey");
2583 		checkForMissingParameter(luiInfo, "luiInfo");
2584 
2585 		// Validate Lui
2586 		List<ValidationResultInfo> val = validateLui("SYSTEM", luiInfo);
2587 		if(null != val && val.size() > 0) {
2588 			throw new DataValidationErrorException("Validation error!", val);
2589 		}
2590 
2591 		Lui lui = new Lui();
2592 		luiInfo.setCluId(cluId);
2593 		luiInfo.setAtpId(atpKey);
2594 
2595 		try {
2596 			lui = LuServiceAssembler.toLui(false, luiInfo, luDao);
2597 		} catch (VersionMismatchException vme) {
2598 		}
2599 
2600 		luDao.create(lui);
2601 
2602 		return LuServiceAssembler.toLuiInfo(lui);
2603 	}
2604 
2605 	@Override
2606 	@Transactional(readOnly=false)
2607 	public LuiInfo updateLui(String luiId, LuiInfo luiInfo)
2608 			throws DataValidationErrorException, DoesNotExistException,
2609 			InvalidParameterException, MissingParameterException,
2610 			OperationFailedException, PermissionDeniedException,
2611 			VersionMismatchException {
2612 
2613 		checkForMissingParameter(luiId, "luiId");
2614 		checkForMissingParameter(luiInfo, "luiInfo");
2615 
2616 		// Validate Lui
2617 		List<ValidationResultInfo> val = validateLui("SYSTEM", luiInfo);
2618 		if(null != val && val.size() > 0) {
2619 			throw new DataValidationErrorException("Validation error!", val);
2620 		}
2621 
2622 		Lui lui = luDao.fetch(Lui.class, luiId);
2623 
2624 		if (!String.valueOf(lui.getVersionNumber()).equals(
2625 				luiInfo.getMetaInfo().getVersionInd())) {
2626 			throw new VersionMismatchException(
2627 					"Lui to be updated is not the current version");
2628 		}
2629 
2630 		Clu clu = luDao.fetch(Clu.class, luiInfo.getCluId());
2631 		lui.setClu(clu);
2632 
2633 		lui.setAttributes(LuServiceAssembler.toGenericAttributes(
2634 				LuiAttribute.class, luiInfo.getAttributes(), lui, luDao));
2635 
2636 		// Now copy standard properties
2637 		BeanUtils.copyProperties(luiInfo, lui, new String[] { "cluId",
2638 				"attributes" });
2639 
2640 		Lui updated = luDao.update(lui);
2641 
2642 		return LuServiceAssembler.toLuiInfo(updated);
2643 	}
2644 
2645 	@Override
2646 	@Transactional(readOnly=false)
2647 	public StatusInfo deleteLui(String luiId)
2648 			throws DependentObjectsExistException, DoesNotExistException,
2649 			InvalidParameterException, MissingParameterException,
2650 			OperationFailedException, PermissionDeniedException {
2651 
2652 		checkForMissingParameter(luiId, "luiId");
2653 
2654 		luDao.delete(Lui.class, luiId);
2655 
2656 		StatusInfo statusInfo = new StatusInfo();
2657 		statusInfo.setSuccess(true);
2658 
2659 		return statusInfo;
2660 	}
2661 
2662 	@Override
2663 	@Transactional(readOnly=false)
2664 	public LuiInfo updateLuiState(String luiId, String luiState)
2665 			throws DataValidationErrorException, DoesNotExistException,
2666 			InvalidParameterException, MissingParameterException,
2667 			OperationFailedException, PermissionDeniedException {
2668 
2669 		// check for missing params
2670 		checkForMissingParameter(luiId, "luiId");
2671 		checkForMissingParameter(luiState, "luiState");
2672 		Lui lui = luDao.fetch(Lui.class, luiId);
2673 		lui.setState(luiState);
2674 		Lui updated = luDao.update(lui);
2675 		return LuServiceAssembler.toLuiInfo(updated);
2676 	}
2677 
2678 	@Override
2679 	public List<ValidationResultInfo> validateLuiLuiRelation(
2680 			String validationType, LuiLuiRelationInfo luiLuiRelationInfo)
2681 			throws DoesNotExistException, InvalidParameterException,
2682 			MissingParameterException, OperationFailedException {
2683 		checkForMissingParameter(validationType, "validationType");
2684 		checkForMissingParameter(luiLuiRelationInfo, "luiLuiRelationInfo");
2685 
2686         ObjectStructureDefinition objStructure = this.getObjectStructure(LuiLuiRelation.class.getName());
2687         Validator defaultValidator = validatorFactory.getValidator();
2688         List<ValidationResultInfo> validationResults = defaultValidator.validateObject(luiLuiRelationInfo, objStructure);
2689         return validationResults;
2690 	}
2691 
2692 	@Override
2693 	@Transactional(readOnly=false)
2694 	public LuiLuiRelationInfo createLuiLuiRelation(String luiId,
2695 			String relatedLuiId, String luLuRelationTypeKey,
2696 			LuiLuiRelationInfo luiLuiRelationInfo)
2697 			throws AlreadyExistsException, CircularRelationshipException,
2698 			DataValidationErrorException, DoesNotExistException,
2699 			InvalidParameterException, MissingParameterException,
2700 			OperationFailedException, PermissionDeniedException {
2701 		checkForMissingParameter(luiId, "luiId");
2702 		checkForMissingParameter(relatedLuiId, "relatedLuiId");
2703 		checkForMissingParameter(luLuRelationTypeKey, "luLuRelationTypeKey");
2704 		checkForMissingParameter(luiLuiRelationInfo, "luiLuiRelationInfo");
2705 
2706 		// Validate LuiLuiRelation
2707 		List<ValidationResultInfo> val = validateLuiLuiRelation("SYSTEM", luiLuiRelationInfo);
2708 		if(null != val && val.size() > 0) {
2709 			throw new DataValidationErrorException("Validation error!", val);
2710 		}
2711 
2712 		if (luiId.equals(relatedLuiId)) {
2713 			throw new CircularRelationshipException(
2714 					"Can not relate a Lui to itself");
2715 		}
2716 
2717 		Lui lui = luDao.fetch(Lui.class, luiId);
2718 		Lui relatedLui = luDao.fetch(Lui.class, relatedLuiId);
2719 
2720 		LuiLuiRelation luiLuiRelation = new LuiLuiRelation();
2721 		BeanUtils.copyProperties(luiLuiRelationInfo, luiLuiRelation,
2722 				new String[] { "luiId", "relatedLuiId", "attributes",
2723 						"metaInfo" });
2724 
2725 		luiLuiRelation.setLui(lui);
2726 		luiLuiRelation.setRelatedLui(relatedLui);
2727 		luiLuiRelation.setAttributes(LuServiceAssembler.toGenericAttributes(
2728 				LuiLuiRelationAttribute.class, luiLuiRelationInfo
2729 						.getAttributes(), luiLuiRelation, luDao));
2730 
2731 		LuLuRelationType luLuRelationType = luDao.fetch(LuLuRelationType.class,
2732 				luLuRelationTypeKey);
2733 
2734 		luiLuiRelation.setLuLuRelationType(luLuRelationType);
2735 
2736 		luDao.create(luiLuiRelation);
2737 
2738 		return LuServiceAssembler.toLuiLuiRelationInfo(luiLuiRelation);
2739 	}
2740 
2741 	@Override
2742 	@Transactional(readOnly=false)
2743 	public LuiLuiRelationInfo updateLuiLuiRelation(String luiLuiRelationId,
2744 			LuiLuiRelationInfo luiLuiRelationInfo)
2745 			throws DataValidationErrorException, DoesNotExistException,
2746 			InvalidParameterException, MissingParameterException,
2747 			OperationFailedException, PermissionDeniedException,
2748 			VersionMismatchException {
2749 
2750 		checkForMissingParameter(luiLuiRelationId, "luiLuiRelationId");
2751 		checkForMissingParameter(luiLuiRelationInfo, "luiLuiRelationInfo");
2752 
2753 		// Validate LuiLuiRelation
2754 		List<ValidationResultInfo> val = validateLuiLuiRelation("SYSTEM", luiLuiRelationInfo);
2755 		if(null != val && val.size() > 0) {
2756 			throw new DataValidationErrorException("Validation error!", val);
2757 		}
2758 
2759 		LuiLuiRelation luiLuiRelation = luDao.fetch(LuiLuiRelation.class,
2760 				luiLuiRelationId);
2761 
2762 		if (!String.valueOf(luiLuiRelation.getVersionNumber()).equals(
2763 				luiLuiRelationInfo.getMetaInfo().getVersionInd())) {
2764 			throw new VersionMismatchException(
2765 					"LuiLuiRelation to be updated is not the current version");
2766 		}
2767 
2768 		BeanUtils.copyProperties(luiLuiRelationInfo, luiLuiRelation,
2769 				new String[] { "luiId", "relatedLuiId", "attributes",
2770 						"metaInfo" });
2771 
2772 		if (!luiLuiRelationInfo.getLuiId().equals(
2773 				luiLuiRelation.getLui().getId())) {
2774 			luiLuiRelation.setLui(luDao.fetch(Lui.class, luiLuiRelationInfo
2775 					.getLuiId()));
2776 		}
2777 
2778 		if (!luiLuiRelationInfo.getRelatedLuiId().equals(
2779 				luiLuiRelation.getRelatedLui().getId())) {
2780 			luiLuiRelation.setRelatedLui(luDao.fetch(Lui.class,
2781 					luiLuiRelationInfo.getRelatedLuiId()));
2782 		}
2783 
2784 		luiLuiRelation.setAttributes(LuServiceAssembler.toGenericAttributes(
2785 				LuiLuiRelationAttribute.class, luiLuiRelationInfo
2786 						.getAttributes(), luiLuiRelation, luDao));
2787 
2788 		if (!luiLuiRelationInfo.getType().equals(
2789 				luiLuiRelation.getLuLuRelationType().getId())) {
2790 			luiLuiRelation.setLuLuRelationType(luDao.fetch(
2791 					LuLuRelationType.class, luiLuiRelationInfo.getType()));
2792 		}
2793 
2794 		LuiLuiRelation updated = luDao.update(luiLuiRelation);
2795 
2796 		return LuServiceAssembler.toLuiLuiRelationInfo(updated);
2797 	}
2798 
2799 	@Override
2800 	@Transactional(readOnly=false)
2801 	public StatusInfo deleteLuiLuiRelation(String luiLuiRelationId)
2802 			throws DoesNotExistException, InvalidParameterException,
2803 			MissingParameterException, OperationFailedException,
2804 			PermissionDeniedException {
2805 
2806 		checkForMissingParameter(luiLuiRelationId, "luiLuiRelationId");
2807 
2808 		luDao.delete(LuiLuiRelation.class, luiLuiRelationId);
2809 
2810 		StatusInfo statusInfo = new StatusInfo();
2811 		statusInfo.setSuccess(true);
2812 
2813 		return statusInfo;
2814 	}
2815 
2816 	/**************************************************************************
2817 	 * SEARCH OPERATIONS *
2818 	 **************************************************************************/
2819 
2820 	@Override
2821 	public SearchCriteriaTypeInfo getSearchCriteriaType(
2822 			String searchCriteriaTypeKey) throws DoesNotExistException,
2823 			InvalidParameterException, MissingParameterException,
2824 			OperationFailedException {
2825 
2826 		return searchManager.getSearchCriteriaType(searchCriteriaTypeKey);
2827 	}
2828 
2829 	@Override
2830 	public List<SearchCriteriaTypeInfo> getSearchCriteriaTypes()
2831 			throws OperationFailedException {
2832 		return searchManager.getSearchCriteriaTypes();
2833 	}
2834 
2835 	@Override
2836 	public SearchResultTypeInfo getSearchResultType(String searchResultTypeKey)
2837 			throws DoesNotExistException, InvalidParameterException,
2838 			MissingParameterException, OperationFailedException {
2839 		checkForMissingParameter(searchResultTypeKey, "searchResultTypeKey");
2840 		return searchManager.getSearchResultType(searchResultTypeKey);
2841 	}
2842 
2843 	@Override
2844 	public List<SearchResultTypeInfo> getSearchResultTypes()
2845 			throws OperationFailedException {
2846 		return searchManager.getSearchResultTypes();
2847 	}
2848 
2849 	@Override
2850 	public SearchTypeInfo getSearchType(String searchTypeKey)
2851 			throws DoesNotExistException, InvalidParameterException,
2852 			MissingParameterException, OperationFailedException {
2853 		checkForMissingParameter(searchTypeKey, "searchTypeKey");
2854 		return searchManager.getSearchType(searchTypeKey);
2855 	}
2856 
2857 	@Override
2858 	public List<SearchTypeInfo> getSearchTypes()
2859 			throws OperationFailedException {
2860 		return searchManager.getSearchTypes();
2861 	}
2862 
2863 	@Override
2864 	public List<SearchTypeInfo> getSearchTypesByCriteria(
2865 			String searchCriteriaTypeKey) throws DoesNotExistException,
2866 			InvalidParameterException, MissingParameterException,
2867 			OperationFailedException {
2868 		checkForMissingParameter(searchCriteriaTypeKey, "searchCriteriaTypeKey");
2869 		return searchManager.getSearchTypesByCriteria(searchCriteriaTypeKey);
2870 	}
2871 
2872 	@Override
2873 	public List<SearchTypeInfo> getSearchTypesByResult(
2874 			String searchResultTypeKey) throws DoesNotExistException,
2875 			InvalidParameterException, MissingParameterException,
2876 			OperationFailedException {
2877 		checkForMissingParameter(searchResultTypeKey, "searchResultTypeKey");
2878 		return searchManager.getSearchTypesByResult(searchResultTypeKey);
2879 	}
2880 
2881 	private void checkCluAlreadyAdded(CluSet cluSet, String cluId)
2882 			throws OperationFailedException {
2883 		for (CluSetJoinVersionIndClu join : cluSet.getCluVerIndIds()) {
2884 			if (join.getCluVersionIndId().equals(cluId)) {
2885 				throw new OperationFailedException("CluSet already contains Clu (id='" + cluId + "')");
2886 			}
2887 		}
2888 	}
2889 
2890 	private void checkCluSetAlreadyAdded(CluSet cluSet, String cluSetIdToAdd)
2891 			throws OperationFailedException {
2892 		if(cluSet.getCluSets()!=null){
2893 			for (CluSet childCluSet : cluSet.getCluSets()) {
2894 				if (childCluSet.getId().equals(cluSetIdToAdd)) {
2895 					throw new OperationFailedException("CluSet (id=" + cluSet.getId() +
2896 							") already contains CluSet (id='" + cluSetIdToAdd + "')");
2897 				}
2898 			}
2899 		}
2900 	}
2901 
2902 	private void checkCluSetCircularReference(CluSet addedCluSet, String hostCluSetId)
2903 			throws CircularRelationshipException {
2904 		if (addedCluSet.getId().equals(hostCluSetId)) {
2905 			throw new CircularRelationshipException(
2906 					"Cannot add a CluSet (id=" + hostCluSetId + ") to ifself");
2907 		}
2908 		if(addedCluSet.getCluSets()!=null){
2909 			for (CluSet childSet : addedCluSet.getCluSets()) {
2910 				if (childSet.getId().equals(hostCluSetId)) {
2911 					throw new CircularRelationshipException(
2912 							"CluSet (id=" + hostCluSetId +
2913 							") already contains this CluSet (id=" +
2914 							childSet.getId() + ")");
2915 				}
2916 				checkCluSetCircularReference(childSet, hostCluSetId);
2917 			}
2918 		}
2919 	}
2920 
2921 	private void findClusInCluSet(List<String> clus, CluSet parentCluSet)
2922 			throws DoesNotExistException {
2923         List<String> processedCluSetIds = new ArrayList<String>();
2924         doFindClusInCluSet(processedCluSetIds, clus, parentCluSet);
2925 	}
2926 	
2927 	private void doFindClusInCluSet(List<String> processedCluSetIds, 
2928 	        List<String> clus, CluSet parentCluSet) {
2929         for (CluSetJoinVersionIndClu join : parentCluSet.getCluVerIndIds()) {
2930             if (!clus.contains(join.getCluVersionIndId())) {
2931                 clus.add(join.getCluVersionIndId());
2932             }
2933         }
2934         if(parentCluSet.getCluSets()!=null){
2935             for (CluSet cluSet : parentCluSet.getCluSets()) {
2936                 // This condition avoids infinite recursion problem
2937                 if (!processedCluSetIds.contains(cluSet.getId())) {
2938                     processedCluSetIds.add(cluSet.getId());
2939                     doFindClusInCluSet(processedCluSetIds, clus, cluSet);
2940                 }
2941             }
2942         }
2943 	}
2944 
2945 	@Override
2946 	public ObjectStructureDefinition getObjectStructure(String objectTypeKey) {
2947 		return dictionaryServiceDelegate.getObjectStructure(objectTypeKey);
2948 	}
2949 
2950 	@Override
2951 	public List<String> getObjectTypes() {
2952 		return dictionaryServiceDelegate.getObjectTypes();
2953 	}
2954 
2955 	public LuDao getLuDao() {
2956 		return luDao;
2957 	}
2958 
2959 	public void setLuDao(LuDao luDao) {
2960 		this.luDao = luDao;
2961 	}
2962 
2963 	@Override
2964 	public SearchResult search(SearchRequest searchRequest) throws MissingParameterException {
2965         checkForMissingParameter(searchRequest, "searchRequest");
2966         return searchManager.search(searchRequest, luDao);
2967 	}
2968 
2969 	/**
2970 	 * Check for missing parameter and throw localized exception if missing
2971 	 *
2972 	 * @param param
2973 	 * @param parameter
2974 	 *            name
2975 	 * @throws MissingParameterException
2976 	 */
2977 	private void checkForMissingParameter(Object param, String paramName)
2978 			throws MissingParameterException {
2979 		if (param == null) {
2980 			throw new MissingParameterException(paramName + " can not be null");
2981 		}
2982 	}
2983 
2984 	/**
2985 	 * @param param
2986 	 * @param paramName
2987 	 * @throws MissingParameterException
2988 	 */
2989 	private void checkForEmptyList(Object param, String paramName)
2990 			throws MissingParameterException {
2991 		if (param != null && param instanceof List<?>
2992 				&& ((List<?>) param).size() == 0) {
2993 			throw new MissingParameterException(paramName
2994 					+ " can not be an empty list");
2995 		}
2996 	}
2997 
2998 	@Override
2999 	@Transactional(readOnly=false)
3000 	public StatusInfo addCluSetsToCluSet(String cluSetId, List<String> cluSetIdList)
3001 		throws CircularRelationshipException,
3002 			DoesNotExistException, InvalidParameterException,
3003 			MissingParameterException, OperationFailedException,
3004 			PermissionDeniedException, UnsupportedActionException {
3005 
3006 		checkForMissingParameter(cluSetId, "cluSetId");
3007 		checkForMissingParameter(cluSetIdList, "cluSetIdList");
3008 
3009 		// Check that CluSet exists
3010 		luDao.fetch(CluSet.class, cluSetId);
3011 
3012 		for(String cluSetIdToAdd : cluSetIdList) {
3013 			StatusInfo status = addCluSetToCluSet(cluSetId, cluSetIdToAdd);
3014 			if (!status.getSuccess()) {
3015 				return status;
3016 			}
3017 		}
3018 
3019 		StatusInfo statusInfo = new StatusInfo();
3020 		statusInfo.setSuccess(true);
3021 
3022 		return statusInfo;
3023 	}
3024 
3025 	@Override
3026 	@Transactional(readOnly=false)
3027 	public StatusInfo addClusToCluSet(List<String> cluIdList, String cluSetId)
3028 		throws DoesNotExistException, InvalidParameterException,
3029 			MissingParameterException, OperationFailedException,
3030 			PermissionDeniedException, UnsupportedActionException {
3031 
3032 		checkForMissingParameter(cluIdList, "cluIdList");
3033 		checkForMissingParameter(cluSetId, "cluSetId");
3034 		
3035 		for(String cluId : cluIdList) {
3036 			StatusInfo status = addCluToCluSet(cluId, cluSetId);
3037 			if (!status.getSuccess()) {
3038 				return status;
3039 			}
3040 		}
3041 
3042 		StatusInfo statusInfo = new StatusInfo();
3043 		statusInfo.setSuccess(true);
3044 
3045 		return statusInfo;
3046 	}
3047 
3048 	public ValidatorFactory getValidatorFactory() {
3049 		return validatorFactory;
3050 	}
3051 
3052 	public void setValidatorFactory(ValidatorFactory validatorFactory) {
3053 		this.validatorFactory = validatorFactory;
3054 	}
3055 
3056 	/********* Versioning Methods ***************************/
3057 	
3058 	@Override
3059     @Transactional(readOnly=false)
3060 	public CluInfo createNewCluVersion(String versionIndCluId, String versionComment) throws DataValidationErrorException, DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException, VersionMismatchException {	    
3061 		Clu latestClu;
3062 		Clu currentClu; 
3063 		try{
3064 			latestClu = luDao.getLatestCluVersion(versionIndCluId);
3065 		}catch(NoResultException e){
3066 			throw new DoesNotExistException("There are no matching versions of this clu", e);
3067 		}
3068 		try{
3069 			currentClu = luDao.getCurrentCluVersion(versionIndCluId);
3070 		}catch(NoResultException e){
3071 			throw new DoesNotExistException("There is no current version of this clu. Only current clus can be versioned. Use setCurrentCluVersion to make a clu current.", e);
3072 		}
3073 		
3074 	    CluInfo cluInfo = LuServiceAssembler.toCluInfo(currentClu);
3075 	    
3076 	    // Reset the Clu
3077 	    clearCluIds(cluInfo);
3078 	    
3079 	    // Create the new Clu Version	    
3080 	    CluInfo newClu = null;
3081 	    
3082         try {
3083     		Clu clu = toCluForCreate(cluInfo.getType(), cluInfo);
3084     	    //Set the Version data
3085     		Version version = new Version();
3086     		version.setSequenceNumber(latestClu.getVersion().getSequenceNumber() + 1);
3087     		version.setVersionIndId(versionIndCluId);
3088     		version.setCurrentVersionStart(null);
3089     		version.setCurrentVersionEnd(null);
3090     		version.setVersionComment(versionComment);
3091     		version.setVersionedFromId(currentClu.getId());
3092     		clu.setVersion(version);
3093     		luDao.create(clu);
3094             newClu = LuServiceAssembler.toCluInfo(clu); 
3095         } catch (AlreadyExistsException e) {
3096             throw new OperationFailedException("Error creating a new clu version", e);
3097         }
3098 	    
3099 	    return newClu;
3100 	}
3101 
3102     private void clearCluIds(CluInfo clu) {
3103 	    // Clear out all ids so a copy can be made
3104         clu.setState(DtoConstants.STATE_DRAFT);// TODO check if this should be set from outside
3105     	clu.setId(null);
3106 	    	    	    
3107 	    if(clu.getAccountingInfo()!=null){
3108 	    	clu.getAccountingInfo().setId(null);
3109 	    
3110 		    for(AffiliatedOrgInfo affiliatedOrg:clu.getAccountingInfo().getAffiliatedOrgs()){
3111 		    	affiliatedOrg.setId(null);
3112 		    }
3113 	    }
3114 	    for(AccreditationInfo accredation:clu.getAccreditations()){
3115 	    	accredation.setId(null);
3116 	    }
3117 	    for(AdminOrgInfo adminOrg:clu.getAdminOrgs()){
3118 	    	adminOrg.setId(null);
3119 	    }
3120 	    for(CluIdentifierInfo alternateIdentifier:clu.getAlternateIdentifiers()){
3121 	    	alternateIdentifier.setId(null);
3122 	    }
3123 	    if(clu.getFeeInfo()!=null){
3124 		    clu.getFeeInfo().setId(null);
3125 		    for(CluFeeRecordInfo cluFeeRecord:clu.getFeeInfo().getCluFeeRecords()){
3126 		    	cluFeeRecord.setId(null);
3127 		    	for(AffiliatedOrgInfo affiliatedOrg:cluFeeRecord.getAffiliatedOrgs()){
3128 		    		affiliatedOrg.setId(null);
3129 		    	}
3130 		    	for(CurrencyAmountInfo feeAmount:cluFeeRecord.getFeeAmounts()){
3131 		    		feeAmount.setId(null);
3132 		    	}
3133 		    }
3134 	    }
3135 	    for(LuCodeInfo luCode:clu.getLuCodes()){
3136 	    	luCode.setId(null);
3137 	    }
3138 	    if(clu.getOfficialIdentifier()!=null){
3139 	    	clu.getOfficialIdentifier().setId(null);
3140 	    }
3141 	}
3142 
3143 	/**
3144 	 * This method sets the CLU with ID of cluVersionId as the current version and will set the version end date of the previously current version to currentVersionStart or now() if null.  This will NOT update state of the current or previously current CLU.  All state changes must be handled either by the business service or from the client application. 
3145 	 * 
3146 	 * @param currentVersionStart if set to null, will default the current version start to the time when this method is called.
3147 	 * You can set this to a future date as well. 
3148 	 */
3149 	@Override
3150 	@Transactional(readOnly=false)
3151     public StatusInfo setCurrentCluVersion(String cluVersionId, Date currentVersionStart) throws DoesNotExistException, InvalidParameterException, MissingParameterException, IllegalVersionSequencingException, OperationFailedException, PermissionDeniedException {
3152         //Check params
3153 		Date currentDbDate = new Date();//FIXME, this should be DB time
3154 		if(currentVersionStart!=null&&currentVersionStart.compareTo(currentDbDate)<0){
3155 			throw new InvalidParameterException("currentVersionStart must be in the future.");
3156 		}
3157 		//Default the currentVersionStart to the current date
3158 		if(currentVersionStart==null){
3159 			currentVersionStart = currentDbDate;
3160 		}
3161 		
3162 		//get the clu we are setting as current 
3163 		Clu clu = luDao.fetch(Clu.class, cluVersionId);
3164 		String versionIndId = clu.getVersion().getVersionIndId();
3165 
3166 		Clu oldClu = null;
3167 		try{
3168 			oldClu = luDao.getCurrentCluVersion(versionIndId);
3169 		}catch(NoResultException e){}
3170 		
3171 		//Check that the clu you are trying to version has a sequence number greater than the current clu
3172 		if(oldClu!=null){
3173 			if(clu.getVersion().getSequenceNumber()<=oldClu.getVersion().getSequenceNumber()){
3174 				throw new OperationFailedException("Clu to make current must have been versioned from the current Clu");
3175 			}
3176 		}else{
3177 			//Ignore the start date set if this is the first version (it will be set to the current time to avoid weird time problems)
3178 			currentVersionStart = currentDbDate;
3179 		}
3180 		
3181 		
3182 		//Get any clus that are set to become current in the future, and clear their current dates
3183 		List<VersionDisplayInfo> versionsInFuture = luDao.getVersionsInDateRange(versionIndId, null, currentDbDate, null);
3184 		for(VersionDisplayInfo versionInFuture:versionsInFuture){
3185 			if(oldClu==null || !versionInFuture.getId().equals(oldClu.getId())){
3186 				VersionEntity futureClu = luDao.fetch(Clu.class, versionInFuture.getId());
3187 				futureClu.getVersion().setCurrentVersionStart(null);
3188 				futureClu.getVersion().setCurrentVersionEnd(null);
3189 				futureClu = luDao.update(futureClu);
3190 			}
3191 		}
3192 		
3193 		//If there is a current clu, set its end date to the new clu's start date
3194 		if(oldClu!=null){
3195 			oldClu.getVersion().setCurrentVersionEnd(currentVersionStart);
3196 			oldClu = luDao.update(oldClu);
3197 		}
3198 		
3199 		//Set the startdate of the new current clu
3200 		clu.getVersion().setCurrentVersionStart(currentVersionStart);
3201 		clu.getVersion().setCurrentVersionEnd(null);
3202 		clu = luDao.update(clu);
3203 		
3204 		StatusInfo statusInfo = new StatusInfo();
3205 		statusInfo.setSuccess(true);
3206         return statusInfo;
3207     }   
3208 	
3209     @Override
3210     public VersionDisplayInfo getLatestVersion(String refObjectTypeURI, String refObjectId) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
3211 		VersionDisplayInfo versionInfo = null;
3212 		if(LuServiceConstants.CLU_NAMESPACE_URI.equals(refObjectTypeURI)){
3213         	try{
3214         		versionInfo = luDao.getLatestVersion(refObjectId, refObjectTypeURI);
3215         	}catch(NoResultException e){
3216         		throw new DoesNotExistException();
3217         	}
3218         }else{
3219         	throw new UnsupportedOperationException("This method does not know how to handle object type:"+refObjectTypeURI);
3220         }
3221 		return versionInfo;
3222 	}
3223 
3224 	@Override
3225     public VersionDisplayInfo getCurrentVersion(String refObjectTypeURI, String refObjectId) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
3226 		VersionDisplayInfo versionInfo = null;
3227 		if(LuServiceConstants.CLU_NAMESPACE_URI.equals(refObjectTypeURI)){
3228         	try{
3229         		versionInfo = luDao.getCurrentCluVersionInfo(refObjectId, refObjectTypeURI);
3230         	}catch(NoResultException e){
3231         		throw new DoesNotExistException();
3232         	}
3233         }else{
3234         	throw new UnsupportedOperationException("This method does not know how to handle object type:"+refObjectTypeURI);
3235         }
3236 		return versionInfo;
3237 	}
3238 
3239     @Override
3240     public VersionDisplayInfo getCurrentVersionOnDate(String refObjectTypeURI, String refObjectId, Date date) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
3241 		VersionDisplayInfo versionInfo = null;
3242 		if(LuServiceConstants.CLU_NAMESPACE_URI.equals(refObjectTypeURI)){
3243         	try{
3244         		versionInfo = luDao.getCurrentVersionOnDate(refObjectId, refObjectTypeURI, date);
3245         	}catch(NoResultException e){
3246         		throw new DoesNotExistException();
3247         	}
3248         }else{
3249         	throw new UnsupportedOperationException("This method does not know how to handle object type:"+refObjectTypeURI);
3250         }
3251 		return versionInfo;
3252     }
3253 
3254     @Override
3255     public VersionDisplayInfo getFirstVersion(String refObjectTypeURI, String refObjectId) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
3256 		VersionDisplayInfo versionInfo = null;
3257 		if(LuServiceConstants.CLU_NAMESPACE_URI.equals(refObjectTypeURI)){
3258         	try{
3259         		versionInfo = luDao.getFirstVersion(refObjectId, refObjectTypeURI);
3260         	}catch(NoResultException e){
3261         		throw new DoesNotExistException();
3262         	}
3263         }else{
3264         	throw new UnsupportedOperationException("This method does not know how to handle object type:"+refObjectTypeURI);
3265         }
3266 		return versionInfo;
3267     }
3268 
3269     @Override
3270     public VersionDisplayInfo getVersionBySequenceNumber(String refObjectTypeURI, String refObjectId, Long sequence) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
3271 		VersionDisplayInfo versionInfo = null;
3272 		if(LuServiceConstants.CLU_NAMESPACE_URI.equals(refObjectTypeURI)){
3273         	try{
3274         		versionInfo = luDao.getVersionBySequenceNumber(refObjectId, refObjectTypeURI, sequence);
3275         	}catch(NoResultException e){
3276         		throw new DoesNotExistException();
3277         	}
3278         }else{
3279         	throw new UnsupportedOperationException("This method does not know how to handle object type:"+refObjectTypeURI);
3280         }
3281 		return versionInfo;
3282     }
3283 
3284     @Override
3285     public List<VersionDisplayInfo> getVersions(String refObjectTypeURI, String refObjectId) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
3286     	List<VersionDisplayInfo> versionInfos = null;
3287 		if(LuServiceConstants.CLU_NAMESPACE_URI.equals(refObjectTypeURI)){
3288        		versionInfos = luDao.getVersions(refObjectId, refObjectTypeURI);
3289        		if(versionInfos==null){
3290        			versionInfos = Collections.emptyList();
3291        		}
3292         }else{
3293         	throw new UnsupportedOperationException("This method does not know how to handle object type:"+refObjectTypeURI);
3294         }
3295 		return versionInfos;
3296     }
3297 
3298     @Override
3299     public List<VersionDisplayInfo> getVersionsInDateRange(String refObjectTypeURI, String refObjectId, Date from, Date to) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
3300     	List<VersionDisplayInfo> versionInfos = null;
3301 		if(LuServiceConstants.CLU_NAMESPACE_URI.equals(refObjectTypeURI)){
3302     		versionInfos = luDao.getVersionsInDateRange(refObjectId, refObjectTypeURI, from, to);
3303        		if(versionInfos==null){
3304        			versionInfos = Collections.emptyList();
3305        		}
3306         }else{
3307         	throw new UnsupportedOperationException("This method does not know how to handle object type:"+refObjectTypeURI);
3308         }
3309 		return versionInfos;
3310     }
3311 }