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