001/**
002 * Copyright 2005-2016 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 */
016package org.kuali.rice.kew.document;
017
018import org.kuali.rice.kew.actionitem.ActionItem;
019import org.kuali.rice.kew.actionitem.OutboxItem;
020import org.kuali.rice.kew.actionlist.service.ActionListService;
021import org.kuali.rice.kew.api.KEWPropertyConstants;
022import org.kuali.rice.kew.api.WorkflowRuntimeException;
023import org.kuali.rice.kew.doctype.bo.DocumentType;
024import org.kuali.rice.kew.doctype.service.DocumentTypeService;
025import org.kuali.rice.kew.service.KEWServiceLocator;
026import org.kuali.rice.kew.xml.DocumentTypeXmlParser;
027import org.kuali.rice.kns.datadictionary.MaintainableItemDefinition;
028import org.kuali.rice.kns.datadictionary.MaintainableSectionDefinition;
029import org.kuali.rice.kns.document.MaintenanceDocument;
030import org.kuali.rice.kns.maintenance.KualiMaintainableImpl;
031import org.kuali.rice.kns.maintenance.Maintainable;
032import org.kuali.rice.kns.web.ui.Field;
033import org.kuali.rice.kns.web.ui.Row;
034import org.kuali.rice.kns.web.ui.Section;
035import org.kuali.rice.krad.bo.DocumentHeader;
036import org.kuali.rice.krad.util.KRADUtils;
037
038import java.util.Collection;
039import java.util.HashSet;
040import java.util.List;
041import java.util.Map;
042import java.util.Set;
043
044/**
045 * This class is the maintainable implementation for the Workflow {@link DocumentType} 
046 * 
047 * @author Kuali Rice Team (rice.collab@kuali.org)
048 *
049 */
050public class DocumentTypeMaintainable extends KualiMaintainableImpl {
051    
052    private static final long serialVersionUID = -5920808902137192662L;
053
054    /**
055     * Override the getSections method on this maintainable so that the document type name field
056     * can be set to read-only for 
057     */
058    @Override
059    public List getSections(MaintenanceDocument document, Maintainable oldMaintainable) {
060        List<Section> sections = super.getSections(document, oldMaintainable);
061        // if the document isn't new then we need to make the document type name field read-only
062        if (!document.isNew()) {
063            sectionLoop: for (Section section : sections) {
064                for (Row row : section.getRows()) {
065                    for (Field field : row.getFields()) {
066                        if (KEWPropertyConstants.NAME.equals(field.getPropertyName())) {
067                            field.setReadOnly(true);
068                            break sectionLoop;
069                        }
070                    }
071                }
072            }
073        }
074        return sections;
075    }
076
077    /**
078     * This overridden method resets the name
079     * 
080     *
081     */
082    @Override
083    public void processAfterCopy(MaintenanceDocument document, Map<String, String[]> parameters) {
084        super.processAfterCopy(document, parameters);
085        DocumentType docType = ((DocumentType)getBusinessObject());
086        docType.setDocumentTypeId(null);
087        docType.setName("");
088        docType.setPreviousVersionId(null);
089        docType.setObjectId(null);
090        docType.setVersionNumber(null);
091    }
092
093    @Override
094    public void doRouteStatusChange(DocumentHeader documentHeader) {
095        super.doRouteStatusChange(documentHeader);
096    }
097    
098    private Set<String> constructUserInterfaceEditablePropertyNamesList() {
099        Set<String> propertyNames = new HashSet<String>();
100        List<MaintainableSectionDefinition> sectionDefinitions = getMaintenanceDocumentDictionaryService().getMaintainableSections(getDocumentTypeName());
101        for (MaintainableSectionDefinition maintainableSectionDefinition : sectionDefinitions) {
102            for (MaintainableItemDefinition maintainableItemDefinition : maintainableSectionDefinition.getMaintainableItems()) {
103                propertyNames.add(maintainableItemDefinition.getName());
104            }
105        }
106        return propertyNames;
107    }
108
109    /**
110     * This is a complete override which does not call into
111     * {@link KualiMaintainableImpl}. This method calls
112     * {@link DocumentTypeService#versionAndSave(DocumentType)}.
113     *
114     */
115    @Override
116    public void saveBusinessObject() {
117        DocumentTypeService docTypeService = KEWServiceLocator.getDocumentTypeService();
118        DocumentType newDocumentType = (DocumentType) getBusinessObject();
119        String documentTypeName = newDocumentType.getName();
120        DocumentType docTypeFromDatabase = docTypeService.findByName(documentTypeName);
121        if (docTypeFromDatabase == null) {
122            docTypeService.versionAndSave(newDocumentType);
123        }
124        else {
125            Boolean applyRetroactively = newDocumentType.getApplyRetroactively();
126                DocumentType newDocumentTypeFromDatabase;
127            DocumentTypeXmlParser parser = new DocumentTypeXmlParser();
128            try {
129                newDocumentTypeFromDatabase = parser.generateNewDocumentTypeFromExisting(documentTypeName);
130            } catch (Exception e) {
131                throw new WorkflowRuntimeException("Error while attempting to generate new document type from existing " +
132                                "database document type with name '" + documentTypeName + "'", e);
133            }
134            newDocumentTypeFromDatabase.populateDataDictionaryEditableFields(constructUserInterfaceEditablePropertyNamesList(), newDocumentType);
135            docTypeService.versionAndSave(newDocumentTypeFromDatabase);
136            if (KRADUtils.isNotNull(applyRetroactively) && applyRetroactively.booleanValue()) {
137                // save all previous instances of document type with the same name
138                // fields: label, description, unresolvedHelpDefinitionUrl
139                List<DocumentType> previousDocTypeInstances = docTypeService.findPreviousInstances(documentTypeName);
140                for (DocumentType prevDocType : previousDocTypeInstances) {
141                    // set up fields
142                    prevDocType.setLabel(newDocumentType.getLabel());
143                    prevDocType.setDescription(newDocumentType.getDescription());
144                    prevDocType.setUnresolvedHelpDefinitionUrl(newDocumentType.getUnresolvedHelpDefinitionUrl());
145                    prevDocType.setUnresolvedDocSearchHelpUrl(newDocumentType.getUnresolvedDocSearchHelpUrl());
146                    docTypeService.save(prevDocType);
147                }
148                // save all former/current action items matching document type name
149                // fields: docLabel
150                ActionListService actionListService = KEWServiceLocator.getActionListService(); 
151                Collection<ActionItem> items = actionListService.findByDocumentTypeName(documentTypeName);
152                for (ActionItem actionItem : items) {
153                    actionItem.setDocLabel(newDocumentType.getLabel());
154                    actionListService.saveActionItem(actionItem);
155                }
156                // save all former/current outbox action items matching document type name
157                // fields: docLabel
158                Collection<OutboxItem> outboxItems = actionListService.getOutboxItemsByDocumentType(documentTypeName);
159                for (OutboxItem outboxItem : outboxItems) {
160                    outboxItem.setDocLabel(newDocumentType.getLabel());
161                    actionListService.saveOutboxItem(outboxItem);
162                }
163            }
164        }
165    }
166
167}