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.assembly;
17  
18  import java.util.ArrayList;
19  import java.util.Iterator;
20  import java.util.LinkedHashMap;
21  import java.util.List;
22  import java.util.Map;
23  
24  import org.apache.log4j.Logger;
25  import org.kuali.student.lum.common.client.lo.MetaInfoHelper;
26  import org.kuali.student.lum.common.client.widgets.CluSetHelper;
27  import org.kuali.student.lum.common.client.widgets.CluSetRangeHelper;
28  import org.kuali.student.lum.common.client.widgets.CluSetRangeModelUtil;
29  import org.kuali.student.r1.common.assembly.data.AssemblyException;
30  import org.kuali.student.r1.common.assembly.data.Data;
31  import org.kuali.student.r1.common.assembly.data.Data.Property;
32  import org.kuali.student.r1.common.assembly.data.Metadata;
33  import org.kuali.student.r1.common.assembly.dictionary.MetadataServiceImpl;
34  import org.kuali.student.r1.common.assembly.old.BaseAssembler;
35  import org.kuali.student.r1.common.assembly.old.data.SaveResult;
36  import org.kuali.student.r2.common.dto.AttributeInfo;
37  import org.kuali.student.r2.common.dto.MetaInfo;
38  import org.kuali.student.r2.common.dto.RichTextInfo;
39  import org.kuali.student.r2.common.dto.ValidationResultInfo;
40  import org.kuali.student.r2.common.exceptions.DoesNotExistException;
41  import org.kuali.student.r2.common.exceptions.InvalidParameterException;
42  import org.kuali.student.r2.common.exceptions.MissingParameterException;
43  import org.kuali.student.r2.common.exceptions.OperationFailedException;
44  import org.kuali.student.r2.common.exceptions.PermissionDeniedException;
45  import org.kuali.student.r2.common.infc.ValidationResult.ErrorLevel;
46  import org.kuali.student.r2.core.search.dto.SearchRequestInfo;
47  import org.kuali.student.r2.core.search.dto.SearchResultCellInfo;
48  import org.kuali.student.r2.core.search.dto.SearchResultInfo;
49  import org.kuali.student.r2.core.search.dto.SearchResultRowInfo;
50  import org.kuali.student.r2.common.util.ContextUtils;
51  import org.kuali.student.r2.core.versionmanagement.dto.VersionDisplayInfo;
52  import org.kuali.student.r2.lum.clu.dto.CluInfo;
53  import org.kuali.student.r2.lum.clu.dto.CluSetInfo;
54  import org.kuali.student.r2.lum.clu.dto.MembershipQueryInfo;
55  import org.kuali.student.r2.lum.clu.service.CluService;
56  import org.kuali.student.r2.lum.util.constants.CluServiceConstants;
57  import org.springframework.transaction.annotation.Transactional;
58  
59  @Transactional(readOnly=true,rollbackFor={Throwable.class})
60  public class CluSetManagementAssembler extends BaseAssembler<Data, Void> {
61  //  TODO Split out CluInfo assembly to its own class
62  
63      final Logger LOG = Logger.getLogger(CluSetManagementAssembler.class);
64  
65      public static final String JOINT_RELATION_TYPE = "kuali.lu.relation.type.co-located";
66  // FIXME: should have it's own proposal types
67      public static final String FORMAT_LU_TYPE = "kuali.lu.type.CreditCourseFormatShell";
68  
69      public static final String FORMAT_RELATION_TYPE = "luLuRelationType.hasCourseFormat";
70      public static final String ACTIVITY_RELATION_TYPE = "luLuRelationType.contains";
71  
72      public static final String PROPOSAL_REFERENCE_TYPE = "kuali.proposal.referenceType.clu"; // <- what the service says, but the dictionary says: "kuali.referenceType.CLU";
73  //    public static final String CREDIT_COURSE_PROPOSAL_DATA_TYPE = "CreditCourseProposal";
74      public static final String CLUSET_DATA_TYPE = "cluset";
75  
76      private CluService cluService;
77      private MetadataServiceImpl metadataService;
78  
79      public MetadataServiceImpl getMetadataService() {
80          return metadataService;
81      }
82  
83      public void setMetadataService(MetadataServiceImpl metadataService) {
84          this.metadataService = metadataService;
85      }
86  
87      @Override
88      public Data get(String id) throws AssemblyException {
89  
90          CluSetHelper resultCluSetHelper = null;
91          Data resultData = null;
92  
93          try {
94              CluSetInfo cluSetInfo = getCluSetInfo(id);
95              resultCluSetHelper = toCluSetHelper(cluSetInfo);
96              if (resultCluSetHelper == null) {
97                  resultData = null;
98              } else {
99  //                resultData = new Data();
100 //                resultData.set("cluset", resultCluSetHelper.getData());
101                 resultData = resultCluSetHelper.getData();
102             }
103         } catch (Exception e) {
104             throw new AssemblyException("Could not retrive cluSet with id " + id, e);
105         }
106 
107         return resultData;
108     }
109     
110     public CluSetInfo getCluSetInfo(String cluSetId) throws Exception {
111         List<String> cluIds = null;
112         CluSetInfo cluSetInfo = null;
113         // note: the cluIds returned by cluService.getCluSetInfo also contains the clus
114         //       that are the result of query parameter search.  Set to null here and
115         //       retrieve the clus that are direct members.
116         cluSetInfo = cluService.getCluSet(cluSetId, ContextUtils.getContextInfo());
117         cluSetInfo.setCluIds(null);
118         cluIds = cluService.getCluIdsFromCluSet(cluSetId, ContextUtils.getContextInfo());
119         cluSetInfo.setCluIds(cluIds);
120         upWrap(cluSetInfo);
121         return cluSetInfo;
122     }
123 
124     public MetaInfoHelper toMetaInfoHelper(MetaInfo metaInfo) {
125         MetaInfoHelper metaInfoHelper = null;
126         Data metaData = new Data();
127         if (metaInfo == null) return null;
128         metaInfoHelper = MetaInfoHelper.wrap(metaData);
129         metaInfoHelper.setCreateId(metaInfo.getCreateId());
130         metaInfoHelper.setCreateTime(metaInfo.getCreateTime());
131         metaInfoHelper.setUpdateId(metaInfo.getUpdateId());
132         metaInfoHelper.setUpdateTime(metaInfo.getUpdateTime());
133         metaInfoHelper.setVersionInd(metaInfo.getVersionInd());
134         return metaInfoHelper;
135     }
136 
137     public MetaInfo toMetaInfo(MetaInfoHelper metaInfoHelper) {
138         MetaInfo metaInfo = null;
139         if (metaInfoHelper == null) return null;
140         metaInfo = new MetaInfo();
141         metaInfo.setCreateId(metaInfoHelper.getCreateId());
142         metaInfo.setCreateTime(metaInfoHelper.getCreateTime());
143         metaInfo.setUpdateId(metaInfoHelper.getUpdateId());
144         metaInfo.setUpdateTime(metaInfoHelper.getUpdateTime());
145         metaInfo.setVersionInd(metaInfoHelper.getVersionInd());
146         return metaInfo;
147     }
148 
149     public String richTextToString(RichTextInfo richTextInfo) {
150         String result = null;
151         if (richTextInfo == null) return null;
152         result = richTextInfo.getPlain();
153         return result;
154     }
155 
156     @Override
157 	@Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
158     public SaveResult<Data> save(Data input)     throws AssemblyException {
159 
160         try {
161             SaveResult<Data> result = new SaveResult<Data>();
162             List<ValidationResultInfo> validationResults = validate(input);
163             if (hasValidationErrors(validationResults)) {
164                 result.setValidationResults(validationResults);
165                 result.setValue(input);
166                 return result;
167             }
168 
169             SaveResult<Data> clusetResult = saveCluSet(input);
170             result.setValidationResults(clusetResult.getValidationResults());
171             result.setValue(clusetResult.getValue());
172             return result;
173         } catch (Exception e) {
174             throw new AssemblyException("Unable to save ....", e);
175         }
176     }
177 
178     private void upWrap(CluSetInfo cluSetInfo) throws AssemblyException {
179         List<String> cluSetIds = (cluSetInfo == null)? null : cluSetInfo.getCluSetIds();
180         List<String> unWrappedCluSetIds = null;
181         List<CluSetInfo> wrappedCluSets = null;
182         List<CluSetInfo> subCluSets = null;
183 
184         try {
185             if (cluSetIds != null && !cluSetIds.isEmpty()) {
186                 subCluSets = cluService.getCluSetsByIds(cluSetIds, ContextUtils.getContextInfo());
187             }
188         } catch (Exception e) {
189             LOG.error(e.getMessage(), e);
190             throw new AssemblyException("Failed to retrieve the sub clusets of cluset " +
191                     cluSetInfo.getId());
192         }
193         // goes through the list of sub clusets and ignore the ones that are not reusable
194         if (subCluSets != null) {
195             for (CluSetInfo subCluSet : subCluSets) {
196                 if (subCluSet.getIsReusable()) {
197                     unWrappedCluSetIds = (unWrappedCluSetIds == null)?
198                             new ArrayList<String>() : unWrappedCluSetIds;
199                             unWrappedCluSetIds.add(subCluSet.getId());
200                 } else {
201                     wrappedCluSets = (wrappedCluSets == null)?
202                             new ArrayList<CluSetInfo>() : wrappedCluSets;
203                             wrappedCluSets.add(subCluSet);
204                 }
205             }
206         }
207         cluSetInfo.setCluSetIds(unWrappedCluSetIds);
208         if (wrappedCluSets != null) {
209             for (CluSetInfo wrappedCluSet : wrappedCluSets) {
210                 MembershipQueryInfo mqInfo = wrappedCluSet.getMembershipQuery();
211                 if (wrappedCluSet.getCluIds() != null && !wrappedCluSet.getCluIds().isEmpty()) {
212                     cluSetInfo.setCluIds(wrappedCluSet.getCluIds());
213                 }
214                 if (mqInfo != null && mqInfo.getSearchTypeKey() != null && !mqInfo.getSearchTypeKey().isEmpty()) {
215                     cluSetInfo.setMembershipQuery(mqInfo);
216                 }
217             }
218         }
219     }
220 
221     private void wrap(CluSetInfo cluSetInfo) throws AssemblyException {
222         int numCluSetElementTypes = 0;
223         boolean hasCluIds = false;
224         boolean hasCluSetIds = false;
225         boolean hasMembershipQuery = false;
226         List<String> wrapperCluSetIds = new ArrayList<String>();
227         MembershipQueryInfo mqInfo = null;
228         if (cluSetInfo.getCluIds() != null && !cluSetInfo.getCluIds().isEmpty()) {
229             numCluSetElementTypes++;
230             hasCluIds = true;
231         }
232         if (cluSetInfo.getCluSetIds() != null && !cluSetInfo.getCluSetIds().isEmpty()) {
233             numCluSetElementTypes++;
234             hasCluSetIds = true;
235         }
236         mqInfo = cluSetInfo.getMembershipQuery();
237         if (mqInfo != null && mqInfo.getSearchTypeKey() != null && !mqInfo.getSearchTypeKey().isEmpty()) {
238             numCluSetElementTypes++;
239             hasMembershipQuery = true;
240         }
241         // if more than one type
242         if (numCluSetElementTypes > 1) {
243             if (hasCluIds) {
244                 CluSetInfo wrapperCluSet = new CluSetInfo();
245                 setWrapperCluSetInfoValues(wrapperCluSet, cluSetInfo);
246                 // copy the clus into the wrapper CluSet
247                 wrapperCluSet.setCluIds(cluSetInfo.getCluIds());
248                 cluSetInfo.setCluIds(null);
249                 try {
250                     if (wrapperCluSet.getTypeKey() == null) {
251                 	    wrapperCluSet.setTypeKey("kuali.cluSet.type.CreditCourse");
252                     }
253                     wrapperCluSet = cluService.createCluSet(wrapperCluSet.getTypeKey(), wrapperCluSet, ContextUtils.getContextInfo());
254                 } catch (Exception e) {
255                     LOG.error("Failed to create wrapper cluset",e);
256                     throw new AssemblyException(e);
257                 }
258                 wrapperCluSetIds.add(wrapperCluSet.getId());
259             }
260             if (hasMembershipQuery) {
261                 CluSetInfo wrapperCluSet = new CluSetInfo();
262                 setWrapperCluSetInfoValues(wrapperCluSet, cluSetInfo);
263                 // copy the MembershipQuery into the wrapper CluSet
264                 wrapperCluSet.setMembershipQuery(mqInfo);
265                 cluSetInfo.setMembershipQuery(null);
266                 try {
267                     wrapperCluSet = cluService.createCluSet(wrapperCluSet.getTypeKey(), wrapperCluSet, ContextUtils.getContextInfo());
268                 } catch (Exception e) {
269                     LOG.error("Failed to create wrapper cluset",e);
270                     throw new AssemblyException(e);
271                 }
272                 wrapperCluSetIds.add(wrapperCluSet.getId());
273             }
274             if (hasCluSetIds) {
275                 wrapperCluSetIds.addAll(cluSetInfo.getCluSetIds());
276             }
277             cluSetInfo.setCluSetIds(wrapperCluSetIds);
278         }
279     }
280 
281     private void setWrapperCluSetInfoValues(CluSetInfo wrapperCluSet, CluSetInfo cluSetInfo) {
282         wrapperCluSet.setAdminOrg(cluSetInfo.getAdminOrg());
283         wrapperCluSet.setEffectiveDate(cluSetInfo.getEffectiveDate());
284         wrapperCluSet.setExpirationDate(cluSetInfo.getExpirationDate());
285         wrapperCluSet.setIsReusable(false);
286         wrapperCluSet.setIsReferenceable(false);
287         wrapperCluSet.setName(cluSetInfo.getName());
288         wrapperCluSet.setStateKey(cluSetInfo.getStateKey());
289         wrapperCluSet.setTypeKey(cluSetInfo.getTypeKey());
290     }
291 
292     private SaveResult<Data> saveCluSet(Data input) throws AssemblyException {
293         SaveResult<Data> result = new SaveResult<Data>();
294 //        CluSetHelper cluSetHelper = new CluSetHelper((Data)input.get("cluset"));
295         List<ValidationResultInfo> saveValidationResults = null;
296         CluSetHelper cluSetHelper = new CluSetHelper(input);
297         CluSetInfo cluSetInfo = toCluSetInfo(cluSetHelper);
298         CluSetInfo updatedCluSetInfo = null;
299         CluSetHelper resultCluSetHelper = null;
300         Data resultData = null;
301         wrap(cluSetInfo);
302         
303         if ((cluSetInfo.getCluIds() == null || cluSetInfo.getCluIds().isEmpty()) &&
304                 (cluSetInfo.getCluSetIds() == null || cluSetInfo.getCluSetIds().isEmpty()) &&
305                 (cluSetInfo.getMembershipQuery() == null)){
306             ValidationResultInfo cluSetCannotBeEmpty = new ValidationResultInfo();
307             saveValidationResults = (saveValidationResults == null)? new ArrayList<ValidationResultInfo>() :
308                 saveValidationResults;
309             result.setValue(null);
310             cluSetCannotBeEmpty.setElement("");
311             cluSetCannotBeEmpty.setMessage("Clu set cannot be empty");
312             cluSetCannotBeEmpty.setError("Clu set cannot be empty");
313             cluSetCannotBeEmpty.setLevel(ErrorLevel.ERROR);
314             saveValidationResults.add(cluSetCannotBeEmpty);
315             result.setValidationResults(saveValidationResults);
316             return result;
317         }
318         
319         if (cluSetInfo.getId() != null && cluSetInfo.getId().trim().length() > 0) {
320             try {
321                 updatedCluSetInfo = cluService.updateCluSet(cluSetInfo.getId(), cluSetInfo, ContextUtils.getContextInfo());
322             } catch (Exception e) {
323             	LOG.error("Failed to update cluset",e);
324                 throw new AssemblyException(e);
325             }
326         } else {
327             try {
328                 if (cluSetInfo.getTypeKey() == null) {
329                     cluSetInfo.setTypeKey("kuali.cluSet.type.CreditCourse");
330                 }
331                 updatedCluSetInfo = cluService.createCluSet(cluSetInfo.getTypeKey(), cluSetInfo, ContextUtils.getContextInfo());
332             } catch (Exception e) {
333                 LOG.error("Failed to create cluset",e);
334                 throw new AssemblyException(e);
335             }
336         }
337         try {
338             resultCluSetHelper = toCluSetHelper(updatedCluSetInfo);
339         } catch (Exception e) {
340             throw new AssemblyException(e);
341         }
342         if (resultCluSetHelper == null) {
343             resultData = null;
344         } else {
345 //            resultData = new Data();
346 //            resultData.set("cluset", resultCluSetHelper.getData());
347             resultData = resultCluSetHelper.getData();
348         }
349         result.setValue(resultData);
350         return result;
351     }
352 
353     private List<String> getMembershipQuerySearchResult(MembershipQueryInfo query) throws MissingParameterException, PermissionDeniedException, OperationFailedException, InvalidParameterException {
354         if(query == null) {
355             return null;
356         }
357         SearchRequestInfo sr = new SearchRequestInfo();
358         sr.setSearchKey(query.getSearchTypeKey());
359         sr.setParams(query.getQueryParamValues());
360 
361         SearchResultInfo result = cluService.search(sr, ContextUtils.getContextInfo());
362 
363         List<String> cluIds = new ArrayList<String>();
364         List<SearchResultRowInfo> rows = result.getRows();
365         for(SearchResultRowInfo row : rows) {
366             List<SearchResultCellInfo> cells = row.getCells();
367             for(SearchResultCellInfo cell : cells) {
368                 if(cell.getKey().equals("lu.resultColumn.cluId")) {
369                     cluIds.add(cell.getValue());
370                 }
371             }
372         }
373         return cluIds;
374     }
375 
376     private CluSetHelper toCluSetHelper(CluSetInfo cluSetInfo) throws Exception {
377         Data data = new Data();
378         Data cluSetDetailData = new Data();
379         data.set("cluset", cluSetDetailData);
380         CluSetHelper result = CluSetHelper.wrap(cluSetDetailData);
381         if (cluSetInfo != null) {
382             if (cluSetInfo.getCluIds() != null && !cluSetInfo.getCluIds().isEmpty()) {
383             	List<CluInfo> cluInfos = new ArrayList<CluInfo>();
384             	for(String id:cluSetInfo.getCluIds()){
385             		VersionDisplayInfo versionInfo = cluService.getCurrentVersion(CluServiceConstants.CLU_NAMESPACE_URI, id, ContextUtils.getContextInfo());
386             		cluInfos.add(cluService.getClu(versionInfo.getId(), ContextUtils.getContextInfo()));
387             	}
388                 result.setApprovedClus(new Data());
389                 for (CluInfo cluInfo : cluInfos) {
390                     if (cluInfo.getStateKey().equals("Active")) {
391                         result.getApprovedClus().add(cluInfo.getVersion().getVersionIndId());
392                     } else {
393                         result.getProposedClus().add(cluInfo.getVersion().getVersionIndId());
394                     }
395                     result.getAllClus().add(cluInfo.getVersion().getVersionIndId());
396                 }
397             }
398             if (cluSetInfo.getCluSetIds() != null && !cluSetInfo.getCluSetIds().isEmpty()) {
399                 result.setCluSets(new Data());
400                 for (String cluSetId : cluSetInfo.getCluSetIds()) {
401                     result.getCluSets().add(cluSetId);
402                 }
403             }
404             if (cluSetInfo.getMembershipQuery() != null) {
405                 MembershipQueryInfo mq = cluSetInfo.getMembershipQuery();
406                 List<String> cluRangeCluIds = getMembershipQuerySearchResult(mq);
407                 if (cluRangeCluIds != null) {
408                     result.setCluRangeViewDetails(new Data());
409                     for (String cluRangeCluId : cluRangeCluIds) {
410                         result.getCluRangeViewDetails().add(cluRangeCluId);
411                     }
412                 }
413             }
414             result.setDescription(richTextToString(cluSetInfo.getDescr()));
415             result.setEffectiveDate(cluSetInfo.getEffectiveDate());
416             result.setExpirationDate(cluSetInfo.getExpirationDate());
417             result.setId(cluSetInfo.getId());
418             result.setMetaInfo(toMetaInfoHelper(cluSetInfo.getMeta()));
419             result.setName(cluSetInfo.getName());
420             result.setOrganization(cluSetInfo.getAdminOrg());
421             result.setState(cluSetInfo.getStateKey());
422             result.setType(cluSetInfo.getTypeKey());
423             result.setCluRangeParams(CluSetRangeModelUtil.INSTANCE.toData(
424                     cluSetInfo.getMembershipQuery()));
425             
426             //Add all dynamic attributes
427             for (AttributeInfo attrInfo : cluSetInfo.getAttributes()) {
428                 result.getData().set(attrInfo.getKey(), attrInfo.getValue());
429             }
430         }
431         return result;
432     }
433 
434     private void addToCluIds(Data clusData, final List<String> cluIds) {
435         if (clusData != null) {
436             for (Data.Property p : clusData) {
437                 if(!"_runtimeData".equals(p.getKey())){
438                     String cluId = p.getValue();
439                     cluIds.add(cluId);
440                 }
441             }
442         }
443     }
444 
445     private CluSetInfo toCluSetInfo(CluSetHelper cluSetHelper) {
446         CluSetInfo cluSetInfo = new CluSetInfo();
447         Data approvedClusData = cluSetHelper.getApprovedClus();
448         Data proposedClusData = cluSetHelper.getProposedClus();
449         Data cluSetsData = cluSetHelper.getCluSets();
450         final List<String> cluIds = new ArrayList<String>();
451         List<String> cluSetIds = null;
452 
453         cluSetInfo.setId(cluSetHelper.getId());
454         if (approvedClusData != null) {
455             addToCluIds(approvedClusData, cluIds);
456         }
457         if (proposedClusData != null) {
458             addToCluIds(proposedClusData, cluIds);
459         }
460         if (cluIds != null && !cluIds.isEmpty()) {
461             cluSetInfo.setCluIds(cluIds);
462         }
463         if (cluSetsData != null) {
464             for (Data.Property p : cluSetsData) {
465                 if(!"_runtimeData".equals(p.getKey())){
466                     String cluSetId = p.getValue();
467                     cluSetIds = (cluSetIds == null)? new ArrayList<String>(3) :
468                         cluSetIds;
469                     cluSetIds.add(cluSetId);
470                 }
471             }
472         }
473         if (cluSetIds != null) {
474             cluSetInfo.setCluSetIds(cluSetIds);
475         }
476         cluSetInfo.setAdminOrg(cluSetHelper.getOrganization());
477         cluSetInfo.setDescr(toRichTextInfo(cluSetHelper.getDescription()));
478         cluSetInfo.setEffectiveDate(cluSetHelper.getEffectiveDate());
479         cluSetInfo.setExpirationDate(cluSetHelper.getExpirationDate());
480         cluSetInfo.setMembershipQuery(toMembershipQueryInfo(cluSetHelper.getCluRangeParams()));
481 
482         cluSetInfo.setMeta(toMetaInfo(cluSetHelper.getMetaInfo()));
483         cluSetInfo.setName(cluSetHelper.getName());
484         cluSetInfo.setStateKey(cluSetHelper.getState());
485         if (cluSetInfo.getStateKey() == null) {
486             cluSetInfo.setStateKey("Active");
487         }
488         cluSetInfo.setTypeKey(cluSetHelper.getType());
489         cluSetInfo.setIsReusable(cluSetHelper.getReusable());
490         cluSetInfo.setIsReferenceable(cluSetHelper.getReferenceable());
491         
492         //Put in any additional properties
493         for(Iterator<Property> iter=cluSetHelper.getData().realPropertyIterator();iter.hasNext();){
494             Property property = iter.next();
495             if(property.getValue()!=null && !(property.getValue() instanceof Data ) && !CluSetHelper.getProperties().contains((String)property.getKey())){
496                 //Add this as a dynamic attribute
497                 cluSetInfo.getAttributes().add(new AttributeInfo((String)property.getKey(), property.getValue().toString()));
498             }
499         }
500         
501         return cluSetInfo;
502     }
503 
504     private MembershipQueryInfo toMembershipQueryInfo(CluSetRangeHelper cluSetRangeHelper) {
505         return CluSetRangeModelUtil.INSTANCE.toMembershipQueryInfo(cluSetRangeHelper.getData());
506     }
507 
508     private RichTextInfo toRichTextInfo(String text) {
509         RichTextInfo result = new RichTextInfo();
510         if (text == null) return null;
511         result.setPlain(text);
512         result.setFormatted(text);
513         return result;
514     }
515 
516     @Override
517     public Data assemble(Void input) throws AssemblyException {
518         throw new UnsupportedOperationException("Data assembly not supported");
519     }
520 
521     @Override
522     public Void disassemble(Data input) throws AssemblyException {
523         throw new UnsupportedOperationException("Data disassembly not supported");
524     }
525 
526     public CluService getCluService() {
527         return cluService;
528     }
529 
530     public void setCluService(CluService cluService) {
531         this.cluService = cluService;
532     }
533 
534 	@Override
535 	protected String getDataType() {
536 		return CLUSET_DATA_TYPE;
537 	}
538 	
539 	@Override
540     public Metadata getDefaultMetadata() {
541         // TODO Auto-generated method stub
542         return metadataService.getMetadata(getDataType());
543     }
544 
545     @Override
546 	protected String getDocumentPropertyName() {
547         return "course";							//FIXME
548 	}
549 
550 	@Override
551 	protected String getDtoName() {
552         return "kuali.lu.type.CreditCourse";		//FIXME
553 	}
554 
555 	@Override
556 	protected Map<String,String> getQualification(String idType, String id) {   //FIXME
557 		String DOCUMENT_TYPE_NAME = "documentTypeName";
558 		Map<String,String> qualification = new LinkedHashMap<String,String>();
559 		qualification.put(DOCUMENT_TYPE_NAME, "CluCreditCourse");
560 		/*
561 		 *	This commented out for permission changes
562 		 *
563 		 *         String QUALIFICATION_PROPOSAL_ID = "courseId";
564 		 *         qualification.put(QUALIFICATION_PROPOSAL_ID, id);
565 		 */
566 		qualification.put(idType, id);
567 		return qualification;
568 	}
569 	
570 }