001/**
002 * Copyright 2005-2014 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.edl.impl.components;
017
018import org.kuali.rice.core.api.uif.RemotableAttributeErrorContract;
019import org.kuali.rice.edl.impl.EDLContext;
020import org.kuali.rice.edl.impl.EDLModelComponent;
021import org.kuali.rice.edl.impl.RequestParser;
022import org.kuali.rice.edl.impl.service.EdlServiceLocator;
023import org.kuali.rice.kew.api.WorkflowDocument;
024import org.kuali.rice.kew.api.WorkflowRuntimeException;
025import org.kuali.rice.kew.api.document.PropertyDefinition;
026import org.kuali.rice.kew.api.document.attribute.WorkflowAttributeDefinition;
027import org.kuali.rice.kew.rule.xmlrouting.XPathHelper;
028import org.w3c.dom.Document;
029import org.w3c.dom.Element;
030import org.w3c.dom.NodeList;
031
032import javax.xml.xpath.XPath;
033import javax.xml.xpath.XPathConstants;
034import java.util.List;
035import java.util.Map;
036
037
038/**
039 * Executes validations and generates XML for workflow attributes that are defined on the EDL Definitions.
040 * These attribute definitions exist in a form similiar to the following:
041 *
042 * <attributes>
043 *   <attribute name="AccountAttribute">
044 *     <field edlField="finCoaCd" attributeField="finCoaCd"/>
045 *     <field edlField="accountNbr" attributeField="accountNbr"/>
046 *     <field edlField="totalDollarAmount" attributeField="totalDollarAmount"/>
047 *   </attribute>
048 * </attributes>
049 *
050 * @author Kuali Rice Team (rice.collab@kuali.org)
051 */
052public class GlobalAttributeComponent extends SimpleWorkflowEDLConfigComponent implements EDLModelComponent  {
053
054        public void updateDOM(Document dom, Element configElement, EDLContext edlContext) {
055            //String action = edlContext.getRequestParser().getPropertyValueAsString(WorkflowDocumentActions.USER_ACTION_REQUEST_KEY);
056            // we don't want to clear the attribute content if they are just opening up the document to view it!
057            if (!edlContext.getUserAction().isLoadAction()) {
058                RequestParser requestParser = edlContext.getRequestParser();
059                try {
060                        WorkflowDocument document = (WorkflowDocument)requestParser.getAttribute(RequestParser.WORKFLOW_DOCUMENT_SESSION_KEY);
061                        //                       clear attribute content so that duplicate attribute values are not added during submission of a new EDL form values version
062                        document.clearAttributeContent();
063                        Document edlDef = EdlServiceLocator.getEDocLiteService().getDefinitionXml(edlContext.getEdocLiteAssociation());
064                        XPath xpath = XPathHelper.newXPath(edlDef);
065                        NodeList attributeNodes = (NodeList)xpath.evaluate("/edl/attributes/attribute", edlDef, XPathConstants.NODESET);
066                        for (int index = 0; index < attributeNodes.getLength(); index++) {
067                                Element attributeElem = (Element)attributeNodes.item(index);
068                                String attributeName = attributeElem.getAttribute("name");
069
070
071                                WorkflowAttributeDefinition.Builder attributeDefBuilder = getWorkflowAttributeDefinitionVO(attributeName, document);
072
073                                NodeList fieldNodes = (NodeList)xpath.evaluate("./field", attributeElem, XPathConstants.NODESET);
074                                for (int fIndex = 0; fIndex < fieldNodes.getLength(); fIndex++) {
075                                        Element fieldElem = (Element)fieldNodes.item(fIndex);
076                                        String edlField = fieldElem.getAttribute("edlField");
077                                        String attributeField = fieldElem.getAttribute("attributeField");
078                                        PropertyDefinition property = attributeDefBuilder.getPropertyDefinition(attributeField);
079                                        String value = requestParser.getParameterValue(edlField);
080                                        if (property == null) {
081                                            property = PropertyDefinition.create(attributeField, value);
082                                        } else {
083                            // modify the current property
084                            attributeDefBuilder.getPropertyDefinitions().remove(property);
085                            property = PropertyDefinition.create(property.getName(), value);
086                                        }
087                                        attributeDefBuilder.addPropertyDefinition(property);
088                                }                               
089                                
090                                // validate if they are taking an action on the document (i.e. it's annotatable)
091                                boolean curAttrValid = true;
092                                if (edlContext.getUserAction().isValidatableAction()) {
093                                    List<? extends RemotableAttributeErrorContract> errors = document.validateAttributeDefinition(attributeDefBuilder.build());
094                                        if (!errors.isEmpty()) {
095                                                edlContext.setInError(true);
096                                                curAttrValid = false;
097                                        }
098                                        Map<String, String> fieldErrors = (Map<String, String>)edlContext.getRequestParser().getAttribute(RequestParser.GLOBAL_FIELD_ERRORS_KEY);
099                                        for (RemotableAttributeErrorContract error : errors) {
100                                            fieldErrors.put(error.getAttributeName(), error.getMessage());
101                                        }
102                                }
103                                
104
105                                if(curAttrValid){
106                   if (edlContext.getUserAction().isValidatableAction()) { 
107                       for (int fIndex = 0; fIndex < fieldNodes.getLength(); fIndex++) {
108                           Element fieldElem = (Element)fieldNodes.item(fIndex);
109                           String edlField = fieldElem.getAttribute("edlField");
110                           String attributeField = fieldElem.getAttribute("attributeField");
111                           PropertyDefinition property = attributeDefBuilder.getPropertyDefinition(attributeField);
112                           String value = requestParser.getParameterValue(edlField);
113                           if (property == null) {
114                               property = PropertyDefinition.create(attributeField, value);                                                     
115                           } else {
116                               // modify the current property
117                               attributeDefBuilder.getPropertyDefinitions().remove(property);
118                               property = PropertyDefinition.create(property.getName(), value);
119                           }
120                           attributeDefBuilder.addPropertyDefinition(property);
121                       }
122                       WorkflowAttributeDefinition attributeDef = attributeDefBuilder.build();
123                       document.addAttributeDefinition(attributeDef);
124                   }
125                                }
126                                
127                                
128
129                        }
130                } catch (Exception e) {
131                        if (e instanceof RuntimeException) {
132                                throw (RuntimeException)e;
133                        }
134                        throw new WorkflowRuntimeException("Failed to process attribute.", e);
135                }
136            }
137        }
138
139    private WorkflowAttributeDefinition.Builder getWorkflowAttributeDefinitionVO(String attributeName, WorkflowDocument document) {
140        for (WorkflowAttributeDefinition attributeDefinition : document.getAttributeDefinitions()) {
141            if (attributeDefinition.getAttributeName().equals(attributeName)) {
142                return WorkflowAttributeDefinition.Builder.create(attributeDefinition);
143            }
144        }
145        return WorkflowAttributeDefinition.Builder.create(attributeName);
146    }
147
148}