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          copyContextsOldToNewBo(document);
92          document.getDocumentHeader().setDocumentDescription("Edited Term Specification Document");
93      }
94  
95      @Override
96      public void processAfterCopy(MaintenanceDocument document, Map<String, String[]> requestParameters) {
97          super.processAfterCopy(document, requestParameters);
98          copyContextsOldToNewBo(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     /**
120      * Overrides the parent method to additionaly clear the contexts list, which is needed for serialization performance
121      * & space.
122      *
123      * @see org.kuali.rice.krad.maintenance.Maintainable#prepareForSave
124      */
125     @Override
126     public void prepareForSave() {
127         super.prepareForSave();
128 
129         TermSpecificationBo termSpec = (TermSpecificationBo) getDataObject();
130         termSpec.getContexts().clear();
131     }
132 
133     /**
134      * For context addition, adds the item to the persisted contextValidTerms collection on the data object.
135      *
136      * <p>Without this step, the context is only added to a transient collection and the relationship will never be
137      * persisted. </p>
138      */
139     @Override
140     public void processAfterAddLine(ViewModel viewModel, Object addLine, String collectionId, String collectionPath,
141             boolean isValidLine) {
142         super.processAfterAddLine(viewModel, addLine, collectionId, collectionPath, isValidLine);
143 
144         // we only want to do our custom processing if a context has been added
145         if (addLine == null || !(addLine instanceof ContextBo)) { return; }
146 
147         ContextBo addedContext = (ContextBo) addLine;
148         TermSpecificationBo termSpec = getDataObjectFromForm(viewModel);
149 
150         boolean alreadyHasContextValidTerm = false;
151 
152         for (ContextValidTermBo contextValidTerm : termSpec.getContextValidTerms()) {
153             if (contextValidTerm.getContextId().equals(addedContext.getId())) {
154                 alreadyHasContextValidTerm = true;
155                 break;
156             }
157         }
158 
159         if (!alreadyHasContextValidTerm) {
160             ContextValidTermBo contextValidTerm = new ContextValidTermBo();
161             contextValidTerm.setContextId(addedContext.getId());
162             contextValidTerm.setTermSpecification(termSpec);
163             termSpec.getContextValidTerms().add(contextValidTerm);
164         }
165     }
166 
167     /**
168      * For context removal, removes the given item from the persisted contextValidTerms collection on the data object.
169      *
170      * <p>Without this step, the context is only removed from a transient collection and the severed relationship will
171      * never be persisted. </p>
172      */
173     @Override
174     public void processCollectionDeleteLine(ViewModel viewModel, String collectionId, String collectionPath,
175             int lineIndex) {
176         super.processCollectionDeleteLine(viewModel, collectionId, collectionPath, lineIndex);
177 
178         List collection = ObjectPropertyUtils.getPropertyValue(viewModel, collectionPath);
179         Object deletedItem = collection.get(lineIndex);
180 
181         // we only want to do our custom processing if a context has been deleted
182         if (deletedItem == null || !(deletedItem instanceof ContextBo)) { return; }
183 
184         ContextBo context = (ContextBo) deletedItem;
185         TermSpecificationBo termSpec = getDataObjectFromForm(viewModel);
186 
187         // find the context and remove it using the special powers of ListIterator
188         ListIterator<ContextValidTermBo> contextValidTermListIter = termSpec.getContextValidTerms().listIterator();
189         while (contextValidTermListIter.hasNext()) {
190             ContextValidTermBo contextValidTerm = contextValidTermListIter.next();
191 
192             if (contextValidTerm.getContextId().equals(context.getId())) {
193                 contextValidTerm.setTermSpecification(null);
194                 contextValidTermListIter.remove();
195             }
196         }
197     }
198 
199     /**
200      * Pulls the data object out of the given form and returns it, casting it to the desired type.
201      *
202      * <p>Assumes that the form is actually a MaintenanceDocumentForm.  The
203      * form.document.newMaintainableObject.dataObject is returned.</p>
204      *
205      * @param form
206      * @param <T> the type of data object to return
207      * @return the data object
208      */
209     private static <T> T getDataObjectFromForm(ViewModel form) {
210         if (form == null) { return null; }
211 
212         return (T) ((MaintenanceDocumentForm)form).getDocument().getNewMaintainableObject().getDataObject();
213     }
214 
215     @Override
216     public Class getDataObjectClass() {
217         return TermSpecificationBo.class;
218     }
219 
220     /**
221      * Recreate the contexts from the contextIDs (needed due to serialization)
222      *
223      * @see org.kuali.rice.krad.maintenance.Maintainable#processAfterRetrieve
224      */
225     @Override
226     public void processAfterRetrieve() {
227         super.processAfterRetrieve();
228 
229         TermSpecificationBo termSpec = (TermSpecificationBo) getDataObject();
230         termSpec.setContexts(new ArrayList<ContextBo>());
231         for (ContextValidTermBo contextValidTerm : termSpec.getContextValidTerms()) {
232             ContextDefinition context = KrmsRepositoryServiceLocator.getContextBoService().getContextByContextId(contextValidTerm.getContextId());
233             termSpec.getContexts().add(ContextBo.from(context));
234             termSpec.getContextIds().add(context.getId());
235         }
236     }
237 }