View Javadoc

1   /**
2    * Copyright 2005-2012 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.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.rice.kew.impl.peopleflow;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
20  import org.kuali.rice.core.api.uif.RemotableAttributeField;
21  import org.kuali.rice.kew.api.KewApiServiceLocator;
22  import org.kuali.rice.kew.api.peopleflow.PeopleFlowDefinition;
23  import org.kuali.rice.kew.api.repository.type.KewTypeDefinition;
24  import org.kuali.rice.kew.framework.peopleflow.PeopleFlowTypeService;
25  import org.kuali.rice.krad.bo.Note;
26  import org.kuali.rice.krad.maintenance.MaintainableImpl;
27  import org.kuali.rice.krad.uif.container.CollectionGroup;
28  import org.kuali.rice.krad.uif.container.Container;
29  import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
30  import org.kuali.rice.krad.uif.view.View;
31  import org.kuali.rice.krad.util.KRADConstants;
32  import org.kuali.rice.krad.web.form.MaintenanceForm;
33  
34  import java.util.ArrayList;
35  import java.util.Collection;
36  import java.util.Collections;
37  import java.util.Comparator;
38  import java.util.List;
39  
40  /**
41   * Custom view helper for the people flow maintenance document to retrieve the type attribute remotable fields
42   *
43   * @author Kuali Rice Team (rice.collab@kuali.org)
44   */
45  public class PeopleFlowMaintainableImpl extends MaintainableImpl {
46  
47  
48      /**
49       * sort {@link org.kuali.rice.kew.impl.peopleflow.PeopleFlowMemberBo}s by stop number (priority)
50       *
51       * @param collection - the Collection to add the given addLine to
52       * @param addLine - the line to add to the given collection
53       * @param insertFirst - indicates if the item should be inserted as the first item
54       */
55      @Override
56      protected void addLine(Collection<Object> collection, Object addLine, boolean insertFirst) {
57          if (collection instanceof List) {
58              ((List) collection).add(0, addLine);
59              if (addLine instanceof PeopleFlowMemberBo) {
60                  Collections.sort((List) collection, new Comparator<Object>() {
61                      public int compare(Object o1, Object o2) {
62                          if ((o1 instanceof PeopleFlowMemberBo) && (o1 instanceof PeopleFlowMemberBo)) {
63                              return ((PeopleFlowMemberBo) o1).getPriority() - ((PeopleFlowMemberBo) o2)
64                                      .getPriority();
65                          }
66                          return 0; // if not both PeopleFlowMemberBo something strange is going on.  Use equals as doing nothing.
67                      }
68                  });
69              }
70          } else {
71              collection.add(addLine);
72          }
73      }
74  
75      /**
76       * Invokes the {@link org.kuali.rice.kew.api.repository.type.KewTypeRepositoryService} to retrieve the remotable
77       * field definitions for the attributes associated with the selected type
78       *
79       * @param view - view instance
80       * @param model - object containing the form data, from which the selected type will be pulled
81       * @param container - container that holds the remotable fields
82       * @return List<RemotableAttributeField> instances for the type attributes, or empty list if not attributes exist
83       */
84      public List<RemotableAttributeField> retrieveTypeAttributes(View view, Object model, Container container) {
85          List<RemotableAttributeField> remoteFields = new ArrayList<RemotableAttributeField>();
86  
87          PeopleFlowBo peopleFlow =
88                  (PeopleFlowBo) ((MaintenanceForm) model).getDocument().getNewMaintainableObject().getDataObject();
89  
90          // retrieve the type service and invoke to get the remotable field definitions
91          String typeId = peopleFlow.getTypeId();
92          if (StringUtils.isNotBlank(typeId)) {
93              KewTypeDefinition typeDefinition = KewApiServiceLocator.getKewTypeRepositoryService().getTypeById(typeId);
94              PeopleFlowTypeService peopleFlowTypeService = GlobalResourceLoader.<PeopleFlowTypeService>getService(
95                      typeDefinition.getServiceName());
96              remoteFields = peopleFlowTypeService.getAttributeFields(typeId);
97          }
98  
99          return remoteFields;
100     }
101 
102     /**
103      * Set the attribute bo list from the map of attribute key/value pairs and then calls
104      * {@link org.kuali.rice.kew.api.peopleflow.PeopleFlowService} to save the people flow instance
105      */
106     @Override
107     public void saveDataObject() {
108         ((PeopleFlowBo) getDataObject()).updateAttributeBoValues();
109 
110         PeopleFlowDefinition peopleFlowDefinition;
111         if (KRADConstants.MAINTENANCE_COPY_ACTION.equals(getMaintenanceAction())) {
112             peopleFlowDefinition = PeopleFlowBo.maintenanceCopy(((PeopleFlowBo) getDataObject()));
113         } else {
114         // this to method ends up copying a versionNumber to null versionNumber 
115             peopleFlowDefinition = PeopleFlowBo.to(((PeopleFlowBo) getDataObject()));
116         }
117         if (StringUtils.isNotBlank(peopleFlowDefinition.getId())) {
118             KewApiServiceLocator.getPeopleFlowService().updatePeopleFlow(peopleFlowDefinition);
119         } else {
120             KewApiServiceLocator.getPeopleFlowService().createPeopleFlow(peopleFlowDefinition);
121         }
122     }
123 
124     /**
125      * In the case of edit maintenance adds a new blank line to the old side
126      * This method is intended to override the method in MaintainableImpl
127      * but has a different set of parameters, so it is not actually an override.
128      * This version was needed to fetch the old collection from a different path
129      * than MaintainableImpl uses.
130      *
131      * @see org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl#processAfterAddLine(org.kuali.rice.krad.uif.view.View,
132      *      org.kuali.rice.krad.uif.container.CollectionGroup, java.lang.Object,
133      *      java.lang.Object)
134      */
135     protected void processAfterAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine, String collectionPath) {
136         // Check for maintenance documents in edit but exclude notes
137         if (model instanceof MaintenanceForm && KRADConstants.MAINTENANCE_EDIT_ACTION.equals(((MaintenanceForm)model).getMaintenanceAction()) && !(addLine instanceof Note)) {
138 //            MaintenanceForm maintenanceForm = (MaintenanceForm) model;
139 //            MaintenanceDocument document = maintenanceForm.getDocument();
140 
141             // get the old object's collection
142             String oldCollectionPath = collectionPath.replace("newMaintainableObject","oldMaintainableObject");
143             Collection<Object> oldCollection = ObjectPropertyUtils.getPropertyValue(model, oldCollectionPath );
144             try {
145                 Object blankLine = collectionGroup.getCollectionObjectClass().newInstance();
146                 oldCollection.add(blankLine);
147             } catch (Exception e) {
148                 throw new RuntimeException("Unable to create new line instance for old maintenance object", e);
149             }
150         }
151     }
152 
153     /**
154      * This method is an override of ViewHelperService.processCollectionDeleteLine().
155      * It is virtually identical except that a local processAfterDeleteLine() method is called
156      * with a different parameter set than is called from within this method to delete the line
157      * from the old maintainable object.
158      * @see org.kuali.rice.krad.uif.service.ViewHelperService#processCollectionDeleteLine(org.kuali.rice.krad.uif.view.View,
159      *      java.lang.Object, java.lang.String, int)
160      */
161     @Override
162     public void processCollectionDeleteLine(View view, Object model, String collectionPath, int lineIndex) {
163         // get the collection group from the view
164         CollectionGroup collectionGroup = view.getViewIndex().getCollectionGroupByPath(collectionPath);
165         if (collectionGroup == null) {
166             logAndThrowRuntime("Unable to get collection group component for path: " + collectionPath);
167         }
168 
169         // get the collection instance for adding the new line
170         Collection<Object> collection = ObjectPropertyUtils.getPropertyValue(model, collectionPath);
171         if (collection == null) {
172             logAndThrowRuntime("Unable to get collection property from model for path: " + collectionPath);
173         }
174 
175         // TODO: look into other ways of identifying a line so we can deal with
176         // unordered collections
177         if (collection instanceof List) {
178             Object deleteLine = ((List<Object>) collection).get(lineIndex);
179 
180             // validate the delete action is allowed for this line
181             boolean isValid = performDeleteLineValidation(view, collectionGroup, deleteLine);
182             if (isValid) {
183                 ((List<Object>) collection).remove(lineIndex);
184                 processAfterDeleteLine(view, collectionPath, model, lineIndex);
185             }
186         } else {
187             logAndThrowRuntime("Only List collection implementations are supported for the delete by index method");
188         }
189     }
190 
191     /**
192      * In the case of edit maintenance deleted the item on the old side.
193      * This method is intended to override the method in MaintainableImpl
194      * but has a different set of parameters, so it is not actually an override.
195      * This was needed to fetch the old collection from a different path
196      * than MaintainableImpl uses. This version has the path (to the newMaintainableObject
197      * provided as a parameter, this is used to generate a path to the oldMaintainableObject
198      *
199      *
200      * @see org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl#processAfterDeleteLine(View,
201      *      org.kuali.rice.krad.uif.container.CollectionGroup, java.lang.Object,  int)
202      */
203     protected void processAfterDeleteLine(View view, String collectionPath, Object model, int lineIndex) {
204 
205         // Check for maintenance documents in edit
206         if (model instanceof MaintenanceForm && KRADConstants.MAINTENANCE_EDIT_ACTION.equals(((MaintenanceForm)model).getMaintenanceAction())) {
207 
208             // get the old object's collection
209             String oldCollectionPath = collectionPath.replace("newMaintainableObject","oldMaintainableObject");
210             Collection<Object> oldCollection = ObjectPropertyUtils.getPropertyValue(model, oldCollectionPath);
211             try {
212                 // Remove the object at lineIndex from the collection
213                 oldCollection.remove(oldCollection.toArray()[lineIndex]);
214             } catch (Exception e) {
215                 throw new RuntimeException("Unable to delete line instance for old maintenance object", e);
216             }
217         }
218     }
219 
220 
221 }