Coverage Report - org.kuali.student.lum.course.service.assembler.FormatAssembler
 
Classes in this File Line Coverage Branch Coverage Complexity
FormatAssembler
85%
87/102
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.util.UUIDHelper;
 26  
 import org.kuali.student.core.assembly.BOAssembler;
 27  
 import org.kuali.student.core.assembly.BaseDTOAssemblyNode;
 28  
 import org.kuali.student.core.assembly.BaseDTOAssemblyNode.NodeOperation;
 29  
 import org.kuali.student.core.assembly.data.AssemblyException;
 30  
 import org.kuali.student.core.exceptions.DoesNotExistException;
 31  
 import org.kuali.student.core.exceptions.InvalidParameterException;
 32  
 import org.kuali.student.core.exceptions.MissingParameterException;
 33  
 import org.kuali.student.core.exceptions.OperationFailedException;
 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  45
 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  72
                 if (clu == null) {
 59  0
                         return null;
 60  
                 }
 61  
 
 62  72
                 FormatInfo format = (null != formatInfo) ? formatInfo
 63  
                                 : new FormatInfo();
 64  
 
 65  
                 // Copy base properties
 66  72
                 format.setId(clu.getId());
 67  72
                 format.setType(clu.getType());
 68  72
                 format.setState(clu.getState());
 69  72
                 format.setMetaInfo(clu.getMetaInfo());
 70  72
                 format.setAttributes(clu.getAttributes());
 71  
                 
 72  
                 // Don't make any changes to nested datastructures if this is
 73  72
                 if (!shallowBuild) {
 74  
                         // Use the luService to find activities, then convert and add to the
 75  
                         // format
 76  
                         try {
 77  28
                                 List<CluInfo> activities = luService.getRelatedClusByCluId(
 78  
                                                 format.getId(),
 79  
                                                 CourseAssemblerConstants.COURSE_ACTIVITY_RELATION_TYPE);
 80  28
                                 for (CluInfo activity : activities) {
 81  53
                                         ActivityInfo activityInfo = activityAssembler.assemble(
 82  
                                                         activity, null, false);
 83  53
                                         format.getActivities().add(activityInfo);
 84  53
                                 }
 85  0
                         } catch (DoesNotExistException e) {
 86  0
                         } catch (Exception e) {
 87  0
                                 throw new AssemblyException("Error getting related activities", e);
 88  28
                         } 
 89  
                 }
 90  72
                 return format;
 91  
         }
 92  
 
 93  
         @Override
 94  
         public BaseDTOAssemblyNode<FormatInfo, CluInfo> disassemble(
 95  
                         FormatInfo format, NodeOperation operation)
 96  
                         throws AssemblyException {
 97  50
                 BaseDTOAssemblyNode<FormatInfo, CluInfo> result = new BaseDTOAssemblyNode<FormatInfo, CluInfo>(
 98  
                                 this);
 99  50
                 if (format == null) {
 100  
                         // FIXME Unsure now if this is an exception or just return null or
 101  
                         // empty assemblyNode
 102  0
                         throw new AssemblyException("Format can not be null");
 103  
                 }
 104  50
                 if (NodeOperation.CREATE != operation && null == format.getId()) {
 105  0
                         throw new AssemblyException("Course Format Shell's id can not be null");
 106  
                 }
 107  
 
 108  
                 CluInfo clu;
 109  
         try {
 110  50
             clu = (NodeOperation.UPDATE == operation) ? clu = luService.getClu(format.getId()) : new CluInfo();
 111  0
         } catch (Exception e) {
 112  0
             throw new AssemblyException("Error retrieving course format shell during update", e);
 113  50
         } 
 114  
 
 115  
                 // Copy all fields
 116  50
                 clu.setId(UUIDHelper.genStringUUID(format.getId()));// Create the id if
 117  
                                                                                                                         // it's not there
 118  
                                                                                                                         // already(important
 119  
                                                                                                                         // for creating
 120  
                                                                                                                         // relations)
 121  50
                 clu.setType(CourseAssemblerConstants.COURSE_FORMAT_TYPE);
 122  50
                 clu.setState(format.getState());
 123  50
                 clu.setMetaInfo(format.getMetaInfo());
 124  50
                 clu.setAttributes(format.getAttributes());
 125  
 
 126  
                 // Add the Clu to the result
 127  50
                 result.setNodeData(clu);
 128  50
                 result.setOperation(operation);
 129  50
                 result.setBusinessDTORef(format);
 130  
 
 131  
                 // Use the Activity assembler to disassemble the activities and
 132  
                 // relations
 133  
                 List<BaseDTOAssemblyNode<?, ?>> activityResults;
 134  
         try {
 135  50
             activityResults = disassembleActivities(clu.getId(),
 136  
                             format, operation);
 137  50
             result.getChildNodes().addAll(activityResults);
 138  
             
 139  0
         } catch (Exception e) {
 140  0
             throw new AssemblyException("Error while disassembling format", e);
 141  50
         }
 142  
         
 143  50
                 return result;
 144  
         }
 145  
 
 146  
         /**
 147  
          * This method will return assembly nodes representing activities and
 148  
          * activity->format relations for a format based on the operation CREATE:
 149  
          * all activities and format-> activity relations will be created UPDATE:
 150  
          * activities will be taken from the luService and compared with the
 151  
          * incomming format's activities. Any new activites will be created with a
 152  
          * corresponding CluCluRelation Any existing activities will be Updated All
 153  
          * leftover activities and their CluCluRelations will be deleted DELETE: all
 154  
          * activities and their CluCluRelations will be deleted
 155  
          * 
 156  
          * If the Operation
 157  
          * 
 158  
          * @param format
 159  
          * @param result
 160  
          * @param operation
 161  
          * @return List of Assembly nodes
 162  
          * @throws AssemblyException
 163  
          * @throws OperationFailedException 
 164  
          * @throws MissingParameterException 
 165  
          * @throws InvalidParameterException 
 166  
          * @throws DoesNotExistException 
 167  
          */
 168  
         private List<BaseDTOAssemblyNode<?, ?>> disassembleActivities(String nodeId,
 169  
                         FormatInfo format, NodeOperation operation)
 170  
                         throws AssemblyException, DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException {
 171  50
                 List<BaseDTOAssemblyNode<?, ?>> results = new ArrayList<BaseDTOAssemblyNode<?, ?>>();
 172  
 
 173  
                 // Get the current activities and put them in a map of activity
 174  
                 // id/relation id
 175  50
                 Map<String, String> currentActivityIds = new HashMap<String, String>();
 176  
 
 177  50
                 if (!NodeOperation.CREATE.equals(operation)) {
 178  
                         try {
 179  7
                                 List<CluCluRelationInfo> activityRelationships = luService
 180  
                                                 .getCluCluRelationsByClu(format.getId());
 181  
                                 
 182  7
                                 for (CluCluRelationInfo activityRelation : activityRelationships) {
 183  18
                                         if (CourseAssemblerConstants.COURSE_ACTIVITY_RELATION_TYPE
 184  
                                                         .equals(activityRelation.getType())) {
 185  11
                                                 currentActivityIds.put(activityRelation
 186  
                                                                 .getRelatedCluId(), activityRelation.getId());
 187  
                                         }
 188  
                                 }
 189  0
                         } catch (DoesNotExistException e) {
 190  0
                         } catch (Exception e) {
 191  0
                                 throw new AssemblyException("Error getting related activities",        e);
 192  7
                         }
 193  
                 }
 194  
 
 195  
                 // Loop through all the activities in this format
 196  50
                 for (ActivityInfo activity : format.getActivities()) {
 197  
 
 198  
                         // If this is a format create/new activity update then all activities will be created
 199  93
                     if (NodeOperation.CREATE == operation
 200  
                             || (NodeOperation.UPDATE == operation &&  !currentActivityIds.containsKey(activity.getId()))) {
 201  
                         
 202  
                 // the activity does not exist, so create
 203  
                 // Assemble and add the activity
 204  83
                 BaseDTOAssemblyNode<ActivityInfo, CluInfo> activityNode = activityAssembler
 205  
                         .disassemble(activity, NodeOperation.CREATE);
 206  83
                 results.add(activityNode);
 207  
 
 208  
                 // Create the relationship and add it as well
 209  83
                 CluCluRelationInfo relation = new CluCluRelationInfo();
 210  83
                 relation.setCluId(nodeId);
 211  83
                 relation.setRelatedCluId(activityNode.getNodeData().getId());// this should
 212  
                                                             // already be set
 213  
                                                             // even if it's a
 214  
                                                             // create
 215  83
                 relation
 216  
                         .setType(CourseAssemblerConstants.COURSE_ACTIVITY_RELATION_TYPE);
 217  83
                 relation.setState(format.getState());
 218  
 
 219  83
                 BaseDTOAssemblyNode<FormatInfo, CluCluRelationInfo> relationNode = new BaseDTOAssemblyNode<FormatInfo, CluCluRelationInfo>(
 220  
                         null);
 221  83
                 relationNode.setNodeData(relation);
 222  83
                 relationNode.setOperation(NodeOperation.CREATE);
 223  
 
 224  83
                 results.add(relationNode);
 225  83
             } else if (NodeOperation.UPDATE == operation
 226  
                                         && currentActivityIds.containsKey(activity.getId())) {
 227  
                                 // If the format already has this activity, then just update the
 228  
                                 // activity
 229  4
                                 BaseDTOAssemblyNode<ActivityInfo, CluInfo> activityNode = activityAssembler
 230  
                                                 .disassemble(activity, NodeOperation.UPDATE);
 231  4
                                 results.add(activityNode);
 232  
 
 233  
                                 // remove this entry from the map so we can tell what needs to
 234  
                                 // be deleted at the end
 235  4
                                 currentActivityIds.remove(activity.getId());
 236  4
                         } else if (NodeOperation.DELETE == operation
 237  
                     && currentActivityIds.containsKey(activity.getId())) {
 238  
                             
 239  
                 // Delete the Format and its relation
 240  6
                 CluCluRelationInfo relationToDelete = new CluCluRelationInfo();
 241  6
                 relationToDelete.setId( currentActivityIds.get(activity.getId()) );
 242  6
                 BaseDTOAssemblyNode<CourseInfo, CluCluRelationInfo> relationToDeleteNode = new BaseDTOAssemblyNode<CourseInfo, CluCluRelationInfo>(
 243  
                         null);
 244  6
                 relationToDeleteNode.setNodeData(relationToDelete);
 245  6
                 relationToDeleteNode.setOperation(NodeOperation.DELETE);
 246  6
                 results.add(relationToDeleteNode);
 247  
             
 248  6
                 BaseDTOAssemblyNode<ActivityInfo, CluInfo> formatNode = activityAssembler
 249  
                 .disassemble(activity, NodeOperation.DELETE);
 250  6
                 results.add(formatNode);                                
 251  
 
 252  
                 // remove this entry from the map so we can tell what needs to
 253  
                 // be deleted at the end
 254  6
                 currentActivityIds.remove(activity.getId());                            
 255  93
                         }
 256  
                 }         
 257  
 
 258  
         // Now any leftover activity ids are no longer needed, so delete
 259  
         // activities and relations
 260  50
         for (Entry<String, String> entry : currentActivityIds.entrySet()) {
 261  
             // Create a new relation with the id of the relation we want to
 262  
             // delete
 263  1
             CluCluRelationInfo relationToDelete = new CluCluRelationInfo();
 264  1
             relationToDelete.setId(entry.getValue());
 265  1
             BaseDTOAssemblyNode<FormatInfo, CluCluRelationInfo> relationToDeleteNode = new BaseDTOAssemblyNode<FormatInfo, CluCluRelationInfo>(
 266  
                     null);
 267  1
             relationToDeleteNode.setNodeData(relationToDelete);
 268  1
             relationToDeleteNode.setOperation(NodeOperation.DELETE);
 269  1
             results.add(relationToDeleteNode);
 270  
 
 271  1
             CluInfo activityCluToDelete = luService.getClu(entry.getKey());
 272  1
             ActivityInfo activityToDelete = activityAssembler.assemble(activityCluToDelete, null, false);
 273  1
             BaseDTOAssemblyNode<ActivityInfo, CluInfo> activityNode = activityAssembler
 274  
             .disassemble(activityToDelete, NodeOperation.DELETE);
 275  1
             results.add(activityNode);                                            
 276  1
         }
 277  
        
 278  
                 
 279  50
                 return results;
 280  
         }
 281  
 
 282  
         public BOAssembler<ActivityInfo, CluInfo> getActivityAssembler() {
 283  0
                 return activityAssembler;
 284  
         }
 285  
 
 286  
         public void setActivityAssembler(
 287  
                         BOAssembler<ActivityInfo, CluInfo> activityAssembler) {
 288  1
                 this.activityAssembler = activityAssembler;
 289  1
         }
 290  
 
 291  
         public LuService getLuService() {
 292  0
                 return luService;
 293  
         }
 294  
 
 295  
         public void setLuService(LuService luService) {
 296  1
                 this.luService = luService;
 297  1
         }
 298  
 }