Coverage Report - org.kuali.student.lum.course.service.assembler.FormatAssembler
 
Classes in this File Line Coverage Branch Coverage Complexity
FormatAssembler
86%
93/108
82%
33/40
5.714
 
 1  
 /*
 2  
  * Copyright 2008 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 1.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl1.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.student.lum.course.service.assembler;
 17  
 
 18  
 import java.util.ArrayList;
 19  
 import java.util.HashMap;
 20  
 import java.util.List;
 21  
 import java.util.Map;
 22  
 import java.util.Map.Entry;
 23  
 
 24  
 import org.apache.log4j.Logger;
 25  
 import org.kuali.student.common.assembly.BOAssembler;
 26  
 import org.kuali.student.common.assembly.BaseDTOAssemblyNode;
 27  
 import org.kuali.student.common.assembly.BaseDTOAssemblyNode.NodeOperation;
 28  
 import org.kuali.student.common.assembly.data.AssemblyException;
 29  
 import org.kuali.student.common.exceptions.DoesNotExistException;
 30  
 import org.kuali.student.common.exceptions.InvalidParameterException;
 31  
 import org.kuali.student.common.exceptions.MissingParameterException;
 32  
 import org.kuali.student.common.exceptions.OperationFailedException;
 33  
 import org.kuali.student.common.util.UUIDHelper;
 34  
 import org.kuali.student.lum.course.dto.ActivityInfo;
 35  
 import org.kuali.student.lum.course.dto.CourseInfo;
 36  
 import org.kuali.student.lum.course.dto.FormatInfo;
 37  
 import org.kuali.student.lum.lu.dto.CluCluRelationInfo;
 38  
 import org.kuali.student.lum.lu.dto.CluInfo;
 39  
 import org.kuali.student.lum.lu.service.LuService;
 40  
 
 41  
 /**
 42  
  * Assembler for FormatInfo. Assembles/Disassemble FormatInfo from CluInfo and
 43  
  * other structures.
 44  
  * 
 45  
  * @author Kuali Student Team
 46  
  * 
 47  
  */
 48  47
 public class FormatAssembler implements BOAssembler<FormatInfo, CluInfo> {
 49  1
         final static Logger LOG = Logger.getLogger(FormatAssembler.class);
 50  
 
 51  
         private BOAssembler<ActivityInfo, CluInfo> activityAssembler;
 52  
         private LuService luService;
 53  
 
 54  
         @Override
 55  
         public FormatInfo assemble(CluInfo clu, FormatInfo formatInfo,
 56  
                         boolean shallowBuild) throws AssemblyException {
 57  
 
 58  76
                 if (clu == null) {
 59  0
                         return null;
 60  
                 }
 61  
 
 62  76
                 FormatInfo format = (null != formatInfo) ? formatInfo
 63  
                                 : new FormatInfo();
 64  
 
 65  
                 // Copy base properties
 66  76
                 format.setId(clu.getId());
 67  76
                 format.setType(clu.getType());
 68  76
                 format.setState(clu.getState());
 69  76
                 format.setMetaInfo(clu.getMetaInfo());
 70  76
                 format.setAttributes(clu.getAttributes());
 71  76
             format.setDuration(clu.getStdDuration());
 72  76
             format.setTermsOffered(clu.getOfferedAtpTypes());
 73  
                 
 74  
                 // Don't make any changes to nested datastructures if this is
 75  76
                 if (!shallowBuild) {
 76  
                         // Use the luService to find activities, then convert and add to the
 77  
                         // format
 78  
                         try {
 79  30
                                 List<CluInfo> activities = luService.getRelatedClusByCluId(
 80  
                                                 format.getId(),
 81  
                                                 CourseAssemblerConstants.COURSE_ACTIVITY_RELATION_TYPE);
 82  30
                                 for (CluInfo activity : activities) {
 83  57
                                         ActivityInfo activityInfo = activityAssembler.assemble(
 84  
                                                         activity, null, false);
 85  57
                                         format.getActivities().add(activityInfo);
 86  57
                                 }
 87  0
                         } catch (DoesNotExistException e) {
 88  0
                         } catch (Exception e) {
 89  0
                                 throw new AssemblyException("Error getting related activities", e);
 90  30
                         } 
 91  
                 }
 92  76
                 return format;
 93  
         }
 94  
 
 95  
         @Override
 96  
         public BaseDTOAssemblyNode<FormatInfo, CluInfo> disassemble(
 97  
                         FormatInfo format, NodeOperation operation)
 98  
                         throws AssemblyException {
 99  52
                 BaseDTOAssemblyNode<FormatInfo, CluInfo> result = new BaseDTOAssemblyNode<FormatInfo, CluInfo>(
 100  
                                 this);
 101  52
                 if (format == null) {
 102  
                         // FIXME Unsure now if this is an exception or just return null or
 103  
                         // empty assemblyNode
 104  0
                         throw new AssemblyException("Format can not be null");
 105  
                 }
 106  52
                 if (NodeOperation.CREATE != operation && null == format.getId()) {
 107  0
                         throw new AssemblyException("Course Format Shell's id can not be null");
 108  
                 }
 109  
 
 110  
                 CluInfo clu;
 111  
         try {
 112  52
             clu = (NodeOperation.UPDATE == operation) ? clu = luService.getClu(format.getId()) : new CluInfo();
 113  0
         } catch (Exception e) {
 114  0
             throw new AssemblyException("Error retrieving course format shell during update", e);
 115  52
         } 
 116  
 
 117  
                 // Copy all fields
 118  52
                 clu.setId(UUIDHelper.genStringUUID(format.getId()));// Create the id if
 119  
                                                                                                                         // it's not there
 120  
                                                                                                                         // already(important
 121  
                                                                                                                         // for creating
 122  
                                                                                                                         // relations)
 123  52
                 clu.setType(CourseAssemblerConstants.COURSE_FORMAT_TYPE);
 124  52
                 clu.setState(format.getState());
 125  52
                 clu.setMetaInfo(format.getMetaInfo());
 126  52
                 clu.setAttributes(format.getAttributes());
 127  52
                 clu.setStdDuration(format.getDuration());
 128  52
                 clu.setOfferedAtpTypes(format.getTermsOffered());
 129  
                 
 130  
                 // Add the Clu to the result
 131  52
                 result.setNodeData(clu);
 132  52
                 result.setOperation(operation);
 133  52
                 result.setBusinessDTORef(format);
 134  
 
 135  
                 // Use the Activity assembler to disassemble the activities and
 136  
                 // relations
 137  
                 List<BaseDTOAssemblyNode<?, ?>> activityResults;
 138  
         try {
 139  52
             activityResults = disassembleActivities(clu.getId(),
 140  
                             format, operation);
 141  52
             result.getChildNodes().addAll(activityResults);
 142  
             
 143  0
         } catch (Exception e) {
 144  0
             throw new AssemblyException("Error while disassembling format", e);
 145  52
         }
 146  
         
 147  52
                 return result;
 148  
         }
 149  
 
 150  
         /**
 151  
          * This method will return assembly nodes representing activities and
 152  
          * activity->format relations for a format based on the operation CREATE:
 153  
          * all activities and format-> activity relations will be created UPDATE:
 154  
          * activities will be taken from the luService and compared with the
 155  
          * incomming format's activities. Any new activites will be created with a
 156  
          * corresponding CluCluRelation Any existing activities will be Updated All
 157  
          * leftover activities and their CluCluRelations will be deleted DELETE: all
 158  
          * activities and their CluCluRelations will be deleted
 159  
          * 
 160  
          * If the Operation
 161  
          * 
 162  
          * @param format
 163  
          * @param result
 164  
          * @param operation
 165  
          * @return List of Assembly nodes
 166  
          * @throws AssemblyException
 167  
          * @throws OperationFailedException 
 168  
          * @throws MissingParameterException 
 169  
          * @throws InvalidParameterException 
 170  
          * @throws DoesNotExistException 
 171  
          */
 172  
         private List<BaseDTOAssemblyNode<?, ?>> disassembleActivities(String nodeId,
 173  
                         FormatInfo format, NodeOperation operation)
 174  
                         throws AssemblyException, DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException {
 175  52
                 List<BaseDTOAssemblyNode<?, ?>> results = new ArrayList<BaseDTOAssemblyNode<?, ?>>();
 176  
 
 177  
                 // Get the current activities and put them in a map of activity
 178  
                 // id/relation id
 179  52
                 Map<String, String> currentActivityIds = new HashMap<String, String>();
 180  
 
 181  52
                 if (!NodeOperation.CREATE.equals(operation)) {
 182  
                         try {
 183  7
                                 List<CluCluRelationInfo> activityRelationships = luService
 184  
                                                 .getCluCluRelationsByClu(format.getId());
 185  
                                 
 186  7
                                 for (CluCluRelationInfo activityRelation : activityRelationships) {
 187  18
                                         if (CourseAssemblerConstants.COURSE_ACTIVITY_RELATION_TYPE
 188  
                                                         .equals(activityRelation.getType())) {
 189  11
                                                 currentActivityIds.put(activityRelation
 190  
                                                                 .getRelatedCluId(), activityRelation.getId());
 191  
                                         }
 192  
                                 }
 193  0
                         } catch (DoesNotExistException e) {
 194  0
                         } catch (Exception e) {
 195  0
                                 throw new AssemblyException("Error getting related activities",        e);
 196  7
                         }
 197  
                 }
 198  
 
 199  
                 // Loop through all the activities in this format
 200  52
                 for (ActivityInfo activity : format.getActivities()) {
 201  
 
 202  
                         // If this is a format create/new activity update then all activities will be created
 203  97
                     if (NodeOperation.CREATE == operation
 204  
                             || (NodeOperation.UPDATE == operation &&  !currentActivityIds.containsKey(activity.getId()))) {
 205  87
                             activity.setState(format.getState());
 206  
                 // the activity does not exist, so create
 207  
                 // Assemble and add the activity
 208  87
                 BaseDTOAssemblyNode<ActivityInfo, CluInfo> activityNode = activityAssembler
 209  
                         .disassemble(activity, NodeOperation.CREATE);
 210  87
                 results.add(activityNode);
 211  
 
 212  
                 // Create the relationship and add it as well
 213  87
                 CluCluRelationInfo relation = new CluCluRelationInfo();
 214  87
                 relation.setCluId(nodeId);
 215  87
                 relation.setRelatedCluId(activityNode.getNodeData().getId());// this should
 216  
                                                             // already be set
 217  
                                                             // even if it's a
 218  
                                                             // create
 219  87
                 relation
 220  
                         .setType(CourseAssemblerConstants.COURSE_ACTIVITY_RELATION_TYPE);
 221  87
                 relation.setState(format.getState());
 222  
 
 223  87
                 BaseDTOAssemblyNode<FormatInfo, CluCluRelationInfo> relationNode = new BaseDTOAssemblyNode<FormatInfo, CluCluRelationInfo>(
 224  
                         null);
 225  87
                 relationNode.setNodeData(relation);
 226  87
                 relationNode.setOperation(NodeOperation.CREATE);
 227  
 
 228  87
                 results.add(relationNode);
 229  87
             } else if (NodeOperation.UPDATE == operation
 230  
                                         && currentActivityIds.containsKey(activity.getId())) {
 231  
                                 // If the format already has this activity, then just update the
 232  
                                 // activity
 233  4
                     activity.setState(format.getState());
 234  4
                                 BaseDTOAssemblyNode<ActivityInfo, CluInfo> activityNode = activityAssembler
 235  
                                                 .disassemble(activity, NodeOperation.UPDATE);
 236  4
                                 results.add(activityNode);
 237  
 
 238  
                                 // remove this entry from the map so we can tell what needs to
 239  
                                 // be deleted at the end
 240  4
                                 currentActivityIds.remove(activity.getId());
 241  4
                         } else if (NodeOperation.DELETE == operation
 242  
                     && currentActivityIds.containsKey(activity.getId())) {
 243  
                             
 244  
                 // Delete the Format and its relation
 245  6
                 CluCluRelationInfo relationToDelete = new CluCluRelationInfo();
 246  6
                 relationToDelete.setId( currentActivityIds.get(activity.getId()) );
 247  6
                 BaseDTOAssemblyNode<CourseInfo, CluCluRelationInfo> relationToDeleteNode = new BaseDTOAssemblyNode<CourseInfo, CluCluRelationInfo>(
 248  
                         null);
 249  6
                 relationToDeleteNode.setNodeData(relationToDelete);
 250  6
                 relationToDeleteNode.setOperation(NodeOperation.DELETE);
 251  6
                 results.add(relationToDeleteNode);
 252  
             
 253  6
                 BaseDTOAssemblyNode<ActivityInfo, CluInfo> formatNode = activityAssembler
 254  
                 .disassemble(activity, NodeOperation.DELETE);
 255  6
                 results.add(formatNode);                                
 256  
 
 257  
                 // remove this entry from the map so we can tell what needs to
 258  
                 // be deleted at the end
 259  6
                 currentActivityIds.remove(activity.getId());                            
 260  97
                         }
 261  
                 }         
 262  
 
 263  
         // Now any leftover activity ids are no longer needed, so delete
 264  
         // activities and relations
 265  52
         for (Entry<String, String> entry : currentActivityIds.entrySet()) {
 266  
             // Create a new relation with the id of the relation we want to
 267  
             // delete
 268  1
             CluCluRelationInfo relationToDelete = new CluCluRelationInfo();
 269  1
             relationToDelete.setId(entry.getValue());
 270  1
             BaseDTOAssemblyNode<FormatInfo, CluCluRelationInfo> relationToDeleteNode = new BaseDTOAssemblyNode<FormatInfo, CluCluRelationInfo>(
 271  
                     null);
 272  1
             relationToDeleteNode.setNodeData(relationToDelete);
 273  1
             relationToDeleteNode.setOperation(NodeOperation.DELETE);
 274  1
             results.add(relationToDeleteNode);
 275  
 
 276  1
             CluInfo activityCluToDelete = luService.getClu(entry.getKey());
 277  1
             ActivityInfo activityToDelete = activityAssembler.assemble(activityCluToDelete, null, false);
 278  1
             BaseDTOAssemblyNode<ActivityInfo, CluInfo> activityNode = activityAssembler
 279  
             .disassemble(activityToDelete, NodeOperation.DELETE);
 280  1
             results.add(activityNode);                                            
 281  1
         }
 282  
        
 283  
                 
 284  52
                 return results;
 285  
         }
 286  
 
 287  
         public BOAssembler<ActivityInfo, CluInfo> getActivityAssembler() {
 288  0
                 return activityAssembler;
 289  
         }
 290  
 
 291  
         public void setActivityAssembler(
 292  
                         BOAssembler<ActivityInfo, CluInfo> activityAssembler) {
 293  1
                 this.activityAssembler = activityAssembler;
 294  1
         }
 295  
 
 296  
         public LuService getLuService() {
 297  0
                 return luService;
 298  
         }
 299  
 
 300  
         public void setLuService(LuService luService) {
 301  1
                 this.luService = luService;
 302  1
         }
 303  
 }