001    /**
002     * Copyright 2005-2013 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.edl.impl.components;
017    
018    import org.kuali.rice.core.api.uif.RemotableAttributeErrorContract;
019    import org.kuali.rice.edl.impl.EDLContext;
020    import org.kuali.rice.edl.impl.EDLModelComponent;
021    import org.kuali.rice.edl.impl.RequestParser;
022    import org.kuali.rice.edl.impl.service.EdlServiceLocator;
023    import org.kuali.rice.kew.api.WorkflowDocument;
024    import org.kuali.rice.kew.api.WorkflowRuntimeException;
025    import org.kuali.rice.kew.api.document.PropertyDefinition;
026    import org.kuali.rice.kew.api.document.attribute.WorkflowAttributeDefinition;
027    import org.kuali.rice.kew.rule.xmlrouting.XPathHelper;
028    import org.w3c.dom.Document;
029    import org.w3c.dom.Element;
030    import org.w3c.dom.NodeList;
031    
032    import javax.xml.xpath.XPath;
033    import javax.xml.xpath.XPathConstants;
034    import java.util.List;
035    import 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     */
052    public 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    }