001 /**
002 * Copyright 2005-2012 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.kew.impl.peopleflow;
017
018 import org.apache.commons.lang.StringUtils;
019 import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
020 import org.kuali.rice.core.api.uif.RemotableAttributeField;
021 import org.kuali.rice.kew.api.KewApiServiceLocator;
022 import org.kuali.rice.kew.api.peopleflow.PeopleFlowDefinition;
023 import org.kuali.rice.kew.api.repository.type.KewTypeDefinition;
024 import org.kuali.rice.kew.framework.peopleflow.PeopleFlowTypeService;
025 import org.kuali.rice.krad.bo.Note;
026 import org.kuali.rice.krad.maintenance.MaintainableImpl;
027 import org.kuali.rice.krad.uif.container.CollectionGroup;
028 import org.kuali.rice.krad.uif.container.Container;
029 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
030 import org.kuali.rice.krad.uif.view.View;
031 import org.kuali.rice.krad.util.KRADConstants;
032 import org.kuali.rice.krad.web.form.MaintenanceForm;
033
034 import java.util.ArrayList;
035 import java.util.Collection;
036 import java.util.Collections;
037 import java.util.Comparator;
038 import java.util.List;
039
040 /**
041 * Custom view helper for the people flow maintenance document to retrieve the type attribute remotable fields
042 *
043 * @author Kuali Rice Team (rice.collab@kuali.org)
044 */
045 public class PeopleFlowMaintainableImpl extends MaintainableImpl {
046
047
048 /**
049 * sort {@link org.kuali.rice.kew.impl.peopleflow.PeopleFlowMemberBo}s by stop number (priority)
050 *
051 * @param collection - the Collection to add the given addLine to
052 * @param addLine - the line to add to the given collection
053 */
054 @Override
055 protected void addLine(Collection<Object> collection, Object addLine) {
056 if (collection instanceof List) {
057 ((List) collection).add(0, addLine);
058 if (addLine instanceof PeopleFlowMemberBo) {
059 Collections.sort((List) collection, new Comparator<Object>() {
060 public int compare(Object o1, Object o2) {
061 if ((o1 instanceof PeopleFlowMemberBo) && (o1 instanceof PeopleFlowMemberBo)) {
062 return ((PeopleFlowMemberBo) o1).getPriority() - ((PeopleFlowMemberBo) o2)
063 .getPriority();
064 }
065 return 0; // if not both PeopleFlowMemberBo something strange is going on. Use equals as doing nothing.
066 }
067 });
068 }
069 } else {
070 collection.add(addLine);
071 }
072 }
073
074 /**
075 * Invokes the {@link org.kuali.rice.kew.api.repository.type.KewTypeRepositoryService} to retrieve the remotable
076 * field definitions for the attributes associated with the selected type
077 *
078 * @param view - view instance
079 * @param model - object containing the form data, from which the selected type will be pulled
080 * @param container - container that holds the remotable fields
081 * @return List<RemotableAttributeField> instances for the type attributes, or empty list if not attributes exist
082 */
083 public List<RemotableAttributeField> retrieveTypeAttributes(View view, Object model, Container container) {
084 List<RemotableAttributeField> remoteFields = new ArrayList<RemotableAttributeField>();
085
086 PeopleFlowBo peopleFlow =
087 (PeopleFlowBo) ((MaintenanceForm) model).getDocument().getNewMaintainableObject().getDataObject();
088
089 // retrieve the type service and invoke to get the remotable field definitions
090 String typeId = peopleFlow.getTypeId();
091 if (StringUtils.isNotBlank(typeId)) {
092 KewTypeDefinition typeDefinition = KewApiServiceLocator.getKewTypeRepositoryService().getTypeById(typeId);
093 PeopleFlowTypeService peopleFlowTypeService = GlobalResourceLoader.<PeopleFlowTypeService>getService(
094 typeDefinition.getServiceName());
095 remoteFields = peopleFlowTypeService.getAttributeFields(typeId);
096 }
097
098 return remoteFields;
099 }
100
101 /**
102 * Set the attribute bo list from the map of attribute key/value pairs and then calls
103 * {@link org.kuali.rice.kew.api.peopleflow.PeopleFlowService} to save the people flow instance
104 */
105 @Override
106 public void saveDataObject() {
107 ((PeopleFlowBo) getDataObject()).updateAttributeBoValues();
108
109 PeopleFlowDefinition peopleFlowDefinition;
110 if (KRADConstants.MAINTENANCE_COPY_ACTION.equals(getMaintenanceAction())) {
111 peopleFlowDefinition = PeopleFlowBo.maintenanceCopy(((PeopleFlowBo) getDataObject()));
112 } else {
113 // this to method ends up copying a versionNumber to null versionNumber
114 peopleFlowDefinition = PeopleFlowBo.to(((PeopleFlowBo) getDataObject()));
115 }
116 if (StringUtils.isNotBlank(peopleFlowDefinition.getId())) {
117 KewApiServiceLocator.getPeopleFlowService().updatePeopleFlow(peopleFlowDefinition);
118 } else {
119 KewApiServiceLocator.getPeopleFlowService().createPeopleFlow(peopleFlowDefinition);
120 }
121 }
122
123 /**
124 * In the case of edit maintenance adds a new blank line to the old side
125 * This method is intended to override the method in MaintainableImpl
126 * but has a different set of parameters, so it is not actually an override.
127 * This version was needed to fetch the old collection from a different path
128 * than MaintainableImpl uses.
129 *
130 * @see org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl#processAfterAddLine(org.kuali.rice.krad.uif.view.View,
131 * org.kuali.rice.krad.uif.container.CollectionGroup, java.lang.Object,
132 * java.lang.Object)
133 */
134 protected void processAfterAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine, String collectionPath) {
135 // Check for maintenance documents in edit but exclude notes
136 if (model instanceof MaintenanceForm && KRADConstants.MAINTENANCE_EDIT_ACTION.equals(((MaintenanceForm)model).getMaintenanceAction()) && !(addLine instanceof Note)) {
137 // MaintenanceForm maintenanceForm = (MaintenanceForm) model;
138 // MaintenanceDocument document = maintenanceForm.getDocument();
139
140 // get the old object's collection
141 String oldCollectionPath = collectionPath.replace("newMaintainableObject","oldMaintainableObject");
142 Collection<Object> oldCollection = ObjectPropertyUtils.getPropertyValue(model, oldCollectionPath );
143 try {
144 Object blankLine = collectionGroup.getCollectionObjectClass().newInstance();
145 oldCollection.add(blankLine);
146 } catch (Exception e) {
147 throw new RuntimeException("Unable to create new line instance for old maintenance object", e);
148 }
149 }
150 }
151
152 /**
153 * This method is an override of ViewHelperService.processCollectionDeleteLine().
154 * It is virtually identical except that a local processAfterDeleteLine() method is called
155 * with a different parameter set than is called from within this method to delete the line
156 * from the old maintainable object.
157 * @see org.kuali.rice.krad.uif.service.ViewHelperService#processCollectionDeleteLine(org.kuali.rice.krad.uif.view.View,
158 * java.lang.Object, java.lang.String, int)
159 */
160 @Override
161 public void processCollectionDeleteLine(View view, Object model, String collectionPath, int lineIndex) {
162 // get the collection group from the view
163 CollectionGroup collectionGroup = view.getViewIndex().getCollectionGroupByPath(collectionPath);
164 if (collectionGroup == null) {
165 logAndThrowRuntime("Unable to get collection group component for path: " + collectionPath);
166 }
167
168 // get the collection instance for adding the new line
169 Collection<Object> collection = ObjectPropertyUtils.getPropertyValue(model, collectionPath);
170 if (collection == null) {
171 logAndThrowRuntime("Unable to get collection property from model for path: " + collectionPath);
172 }
173
174 // TODO: look into other ways of identifying a line so we can deal with
175 // unordered collections
176 if (collection instanceof List) {
177 Object deleteLine = ((List<Object>) collection).get(lineIndex);
178
179 // validate the delete action is allowed for this line
180 boolean isValid = performDeleteLineValidation(view, collectionGroup, deleteLine);
181 if (isValid) {
182 ((List<Object>) collection).remove(lineIndex);
183 processAfterDeleteLine(view, collectionPath, model, lineIndex);
184 }
185 } else {
186 logAndThrowRuntime("Only List collection implementations are supported for the delete by index method");
187 }
188 }
189
190 /**
191 * In the case of edit maintenance deleted the item on the old side.
192 * This method is intended to override the method in MaintainableImpl
193 * but has a different set of parameters, so it is not actually an override.
194 * This was needed to fetch the old collection from a different path
195 * than MaintainableImpl uses. This version has the path (to the newMaintainableObject
196 * provided as a parameter, this is used to generate a path to the oldMaintainableObject
197 *
198 *
199 * @see org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl#processAfterDeleteLine(View,
200 * org.kuali.rice.krad.uif.container.CollectionGroup, java.lang.Object, int)
201 */
202 protected void processAfterDeleteLine(View view, String collectionPath, Object model, int lineIndex) {
203
204 // Check for maintenance documents in edit
205 if (model instanceof MaintenanceForm && KRADConstants.MAINTENANCE_EDIT_ACTION.equals(((MaintenanceForm)model).getMaintenanceAction())) {
206
207 // get the old object's collection
208 String oldCollectionPath = collectionPath.replace("newMaintainableObject","oldMaintainableObject");
209 Collection<Object> oldCollection = ObjectPropertyUtils.getPropertyValue(model, oldCollectionPath);
210 try {
211 // Remove the object at lineIndex from the collection
212 oldCollection.remove(oldCollection.toArray()[lineIndex]);
213 } catch (Exception e) {
214 throw new RuntimeException("Unable to delete line instance for old maintenance object", e);
215 }
216 }
217 }
218
219
220 }