View Javadoc
1   /**
2    * Copyright 2005-2014 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.krms.impl.ui;
17  
18  import org.apache.commons.collections.CollectionUtils;
19  import org.kuali.rice.krad.maintenance.MaintainableImpl;
20  import org.kuali.rice.krad.maintenance.MaintenanceDocument;
21  import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
22  import org.kuali.rice.krad.uif.view.ViewModel;
23  import org.kuali.rice.krad.util.KRADConstants;
24  import org.kuali.rice.krad.web.form.MaintenanceDocumentForm;
25  import org.kuali.rice.krms.api.repository.context.ContextDefinition;
26  import org.kuali.rice.krms.impl.repository.ContextBo;
27  import org.kuali.rice.krms.impl.repository.ContextValidTermBo;
28  import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator;
29  import org.kuali.rice.krms.impl.repository.TermSpecificationBo;
30  
31  import java.util.ArrayList;
32  import java.util.List;
33  import java.util.ListIterator;
34  import java.util.Map;
35  
36  /**
37   * {@link org.kuali.rice.krad.maintenance.Maintainable} for the {@link AgendaEditor}
38   *
39   * @author Kuali Rice Team (rice.collab@kuali.org)
40   *
41   */
42  public class TermSpecificationMaintainable extends MaintainableImpl {
43  	
44  	private static final long serialVersionUID = 1L;
45  
46      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(TermSpecificationMaintainable.class);
47  
48      @Override
49      public Object retrieveObjectForEditOrCopy(MaintenanceDocument document, Map<String, String> dataObjectKeys) {
50  
51          TermSpecificationBo termSpecificationBo = (TermSpecificationBo) super.retrieveObjectForEditOrCopy(document,
52                  dataObjectKeys);
53  
54          if (!CollectionUtils.isEmpty(termSpecificationBo.getContextValidTerms())) {
55              for (ContextValidTermBo contextValidTerm : termSpecificationBo.getContextValidTerms()) {
56                  ContextDefinition context =
57                          KrmsRepositoryServiceLocator.getContextBoService().getContextByContextId(contextValidTerm.getContextId());
58  
59                  if (context != null) {
60                      termSpecificationBo.getContexts().add(ContextBo.from(context));
61                      termSpecificationBo.getContextIds().add(contextValidTerm.getContextId());
62                  }
63              }
64          }
65  
66          if (KRADConstants.MAINTENANCE_COPY_ACTION.equals(getMaintenanceAction())) {
67              document.getDocumentHeader().setDocumentDescription("New Term Specification Document");
68          }
69  
70          return termSpecificationBo;
71      }
72  
73      /**
74  	 * {@inheritDoc}
75  	 */
76  	@Override
77  	public void processAfterNew(MaintenanceDocument document,
78  		Map<String, String[]> requestParameters) {
79  
80  		super.processAfterNew(document, requestParameters);
81          document.getDocumentHeader().setDocumentDescription("New Term Specification Document");
82  
83  	}
84  
85      /**
86       * {@inheritDoc}
87       */
88      @Override
89      public void processAfterEdit(MaintenanceDocument document, Map<String, String[]> requestParameters) {
90          super.processAfterEdit(document, requestParameters);
91          document.getDocumentHeader().setDocumentDescription("Edited Term Specification Document");
92      }
93  
94      @Override
95      public void processAfterCopy(MaintenanceDocument document, Map<String, String[]> requestParameters) {
96          super.processAfterCopy(document, requestParameters);
97          copyContextsOldToNewBo(document);
98          setNewContextValidTermsNewBO(document);
99      }
100 
101     /**
102      * Copy the contexts from the old TermSpecificationBo to the newTermSpecificationBo of the maintenance document.
103      * <p>
104      * Since the contexts is a transient field it doesn't get copied by the deepCopy in
105      * MaintenanceDocumentServiceImpl.setupMaintenanceObject, we manually need to copy the values over.
106      * For performance reasons a shallow copy is done since the ContextBo themselves are never changed.
107      * </p>
108      * @param document that contains the old and new TermSpecificationBos
109      */
110     private void copyContextsOldToNewBo(MaintenanceDocument document) {
111         TermSpecificationBo oldTermSpec = (TermSpecificationBo) document.getOldMaintainableObject().getDataObject();
112         TermSpecificationBo newTermSpec = (TermSpecificationBo) document.getNewMaintainableObject().getDataObject();
113         newTermSpec.setContexts(new ArrayList<ContextBo>());
114         for (ContextBo contextBo : oldTermSpec.getContexts()) {
115             newTermSpec.getContexts().add(contextBo);
116         }
117     }
118 
119     private void setNewContextValidTermsNewBO(MaintenanceDocument document) {
120         TermSpecificationBo newTermSpec = (TermSpecificationBo) document.getNewMaintainableObject().getDataObject();
121         for (ContextValidTermBo contextValidTermBo : newTermSpec.getContextValidTerms()) {
122             contextValidTermBo.setId(null);
123             contextValidTermBo.setTermSpecification(newTermSpec);
124         }
125     }
126 
127     /**
128      * Overrides the parent method to additionaly clear the contexts list, which is needed for serialization performance
129      * & space.
130      *
131      * @see org.kuali.rice.krad.maintenance.Maintainable#prepareForSave
132      */
133     @Override
134     public void prepareForSave() {
135         super.prepareForSave();
136 
137         TermSpecificationBo termSpec = (TermSpecificationBo) getDataObject();
138         termSpec.getContexts().clear();
139     }
140 
141     /**
142      * For context addition, adds the item to the persisted contextValidTerms collection on the data object.
143      *
144      * <p>Without this step, the context is only added to a transient collection and the relationship will never be
145      * persisted. </p>
146      */
147     @Override
148     public void processAfterAddLine(ViewModel viewModel, Object addLine, String collectionId, String collectionPath,
149             boolean isValidLine) {
150         super.processAfterAddLine(viewModel, addLine, collectionId, collectionPath, isValidLine);
151 
152         // we only want to do our custom processing if a context has been added
153         if (addLine == null || !(addLine instanceof ContextBo)) { return; }
154 
155         ContextBo addedContext = (ContextBo) addLine;
156         TermSpecificationBo termSpec = getDataObjectFromForm(viewModel);
157 
158         boolean alreadyHasContextValidTerm = false;
159 
160         for (ContextValidTermBo contextValidTerm : termSpec.getContextValidTerms()) {
161             if (contextValidTerm.getContextId().equals(addedContext.getId())) {
162                 alreadyHasContextValidTerm = true;
163                 break;
164             }
165         }
166 
167         if (!alreadyHasContextValidTerm) {
168             ContextValidTermBo contextValidTerm = new ContextValidTermBo();
169             contextValidTerm.setContextId(addedContext.getId());
170             contextValidTerm.setTermSpecification(termSpec);
171             termSpec.getContextValidTerms().add(contextValidTerm);
172         }
173     }
174 
175     /**
176      * For context removal, removes the given item from the persisted contextValidTerms collection on the data object.
177      *
178      * <p>Without this step, the context is only removed from a transient collection and the severed relationship will
179      * never be persisted. </p>
180      */
181     @Override
182     public void processCollectionDeleteLine(ViewModel viewModel, String collectionId, String collectionPath,
183             int lineIndex) {
184         List collection = ObjectPropertyUtils.getPropertyValue(viewModel, collectionPath);
185         Object deletedItem = collection.get(lineIndex);
186 
187         // we only want to do our custom processing if a context has been deleted
188         if (deletedItem == null || !(deletedItem instanceof ContextBo)) {
189             super.processCollectionDeleteLine(viewModel, collectionId, collectionPath, lineIndex);
190             return;
191         }
192 
193         ContextBo context = (ContextBo) deletedItem;
194         TermSpecificationBo termSpec = getDataObjectFromForm(viewModel);
195 
196         // find the context and remove it using the special powers of ListIterator
197         ListIterator<ContextValidTermBo> contextValidTermListIter = termSpec.getContextValidTerms().listIterator();
198         while (contextValidTermListIter.hasNext()) {
199             ContextValidTermBo contextValidTerm = contextValidTermListIter.next();
200 
201             if (contextValidTerm.getContextId().equals(context.getId())) {
202                 contextValidTerm.setTermSpecification(null);
203                 contextValidTermListIter.remove();
204             }
205         }
206 
207         super.processCollectionDeleteLine(viewModel, collectionId, collectionPath, lineIndex);
208     }
209 
210     /**
211      * Pulls the data object out of the given form and returns it, casting it to the desired type.
212      *
213      * <p>Assumes that the form is actually a MaintenanceDocumentForm.  The
214      * form.document.newMaintainableObject.dataObject is returned.</p>
215      *
216      * @param form
217      * @param <T> the type of data object to return
218      * @return the data object
219      */
220     private static <T> T getDataObjectFromForm(ViewModel form) {
221         if (form == null) { return null; }
222 
223         return (T) ((MaintenanceDocumentForm)form).getDocument().getNewMaintainableObject().getDataObject();
224     }
225 
226     @Override
227     public Class getDataObjectClass() {
228         return TermSpecificationBo.class;
229     }
230 
231     @Override
232     public void setDataObject(Object object) {
233         List<ContextBo> copiedContexts = new ArrayList<>();
234 
235         for (ContextBo context : ((TermSpecificationBo) object).getContexts()) {
236             copiedContexts.add(ContextBo.from(ContextDefinition.Builder.create( context).build()));
237         };
238 
239         ((TermSpecificationBo) object).setContexts(copiedContexts);
240         super.setDataObject(object);
241     }
242 
243     /**
244      * Recreate the contexts from the contextIDs (needed due to serialization)
245      *
246      * @see org.kuali.rice.krad.maintenance.Maintainable#processAfterRetrieve
247      */
248     @Override
249     public void processAfterRetrieve() {
250         super.processAfterRetrieve();
251 
252         TermSpecificationBo termSpec = (TermSpecificationBo) getDataObject();
253         termSpec.setContexts(new ArrayList<ContextBo>());
254         for (ContextValidTermBo contextValidTerm : termSpec.getContextValidTerms()) {
255             ContextDefinition context = KrmsRepositoryServiceLocator.getContextBoService().getContextByContextId(contextValidTerm.getContextId());
256             termSpec.getContexts().add(ContextBo.from(context));
257             termSpec.getContextIds().add(context.getId());
258         }
259     }
260 }