Coverage Report - org.apache.commons.scxml.model.Assign

Classes in this File Line Coverage Branch Coverage Complexity
Assign
83% 
92% 
2.077

 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.commons.scxml.model;
 18  
 
 19  
 import java.util.Collection;
 20  
 
 21  
 import javax.xml.parsers.DocumentBuilderFactory;
 22  
 
 23  
 import org.apache.commons.logging.Log;
 24  
 import org.apache.commons.logging.LogFactory;
 25  
 import org.apache.commons.scxml.Context;
 26  
 import org.apache.commons.scxml.ErrorReporter;
 27  
 import org.apache.commons.scxml.Evaluator;
 28  
 import org.apache.commons.scxml.EventDispatcher;
 29  
 import org.apache.commons.scxml.PathResolver;
 30  
 import org.apache.commons.scxml.SCInstance;
 31  
 import org.apache.commons.scxml.SCXMLExpressionException;
 32  
 import org.apache.commons.scxml.SCXMLHelper;
 33  
 import org.apache.commons.scxml.TriggerEvent;
 34  
 import org.apache.commons.scxml.semantics.ErrorConstants;
 35  
 import org.w3c.dom.Document;
 36  
 import org.w3c.dom.Node;
 37  
 
 38  
 /**
 39  
  * The class in this SCXML object model that corresponds to the
 40  
  * <assign> SCXML element.
 41  
  *
 42  
  */
 43  
 public class Assign extends Action implements PathResolverHolder {
 44  
 
 45  
     /**
 46  
      * Serial version UID.
 47  
      */
 48  
     private static final long serialVersionUID = 1L;
 49  
 
 50  
     /**
 51  
      * Left hand side expression evaluating to a previously
 52  
      * defined variable.
 53  
      */
 54  
     private String name;
 55  
 
 56  
     /**
 57  
      * Left hand side expression evaluating to a location within
 58  
      * a previously defined XML data tree.
 59  
      */
 60  
     private String location;
 61  
 
 62  
     /**
 63  
      * The source where the new XML instance for this location exists.
 64  
      */
 65  
     private String src;
 66  
 
 67  
     /**
 68  
      * Expression evaluating to the new value of the variable.
 69  
      */
 70  
     private String expr;
 71  
 
 72  
     /**
 73  
      * {@link PathResolver} for resolving the "src" result.
 74  
      */
 75  
     private PathResolver pathResolver;
 76  
 
 77  
     /**
 78  
      * Constructor.
 79  
      */
 80  
     public Assign() {
 81  71
         super();
 82  71
     }
 83  
 
 84  
     /**
 85  
      * Get the variable to be assigned a new value.
 86  
      *
 87  
      * @return Returns the name.
 88  
      */
 89  
     public String getName() {
 90  5
         return name;
 91  
     }
 92  
 
 93  
     /**
 94  
      * Get the variable to be assigned a new value.
 95  
      *
 96  
      * @param name The name to set.
 97  
      */
 98  
     public void setName(final String name) {
 99  52
         this.name = name;
 100  52
     }
 101  
 
 102  
     /**
 103  
      * Get the expr that will evaluate to the new value.
 104  
      *
 105  
      * @return Returns the expr.
 106  
      */
 107  
     public String getExpr() {
 108  5
         return expr;
 109  
     }
 110  
 
 111  
     /**
 112  
      * Set the expr that will evaluate to the new value.
 113  
      *
 114  
      * @param expr The expr to set.
 115  
      */
 116  
     public void setExpr(final String expr) {
 117  66
         this.expr = expr;
 118  66
     }
 119  
 
 120  
     /**
 121  
      * Get the location for a previously defined XML data tree.
 122  
      *
 123  
      * @return Returns the location.
 124  
      */
 125  
     public String getLocation() {
 126  5
         return location;
 127  
     }
 128  
 
 129  
     /**
 130  
      * Set the location for a previously defined XML data tree.
 131  
      *
 132  
      * @param location The location.
 133  
      */
 134  
     public void setLocation(final String location) {
 135  15
         this.location = location;
 136  15
     }
 137  
 
 138  
     /**
 139  
      * Get the source where the new XML instance for this location exists.
 140  
      *
 141  
      * @return Returns the source.
 142  
      */
 143  
     public String getSrc() {
 144  0
         return src;
 145  
     }
 146  
 
 147  
     /**
 148  
      * Set the source where the new XML instance for this location exists.
 149  
      *
 150  
      * @param src The source.
 151  
      */
 152  
     public void setSrc(final String src) {
 153  1
         this.src = src;
 154  1
     }
 155  
 
 156  
     /**
 157  
      * Get the {@link PathResolver}.
 158  
      *
 159  
      * @return Returns the pathResolver.
 160  
      */
 161  
     public PathResolver getPathResolver() {
 162  0
         return pathResolver;
 163  
     }
 164  
 
 165  
     /**
 166  
      * Set the {@link PathResolver}.
 167  
      *
 168  
      * @param pathResolver The pathResolver to set.
 169  
      */
 170  
     public void setPathResolver(final PathResolver pathResolver) {
 171  66
         this.pathResolver = pathResolver;
 172  66
     }
 173  
 
 174  
     /**
 175  
      * {@inheritDoc}
 176  
      */
 177  
     public void execute(final EventDispatcher evtDispatcher,
 178  
             final ErrorReporter errRep, final SCInstance scInstance,
 179  
             final Log appLog, final Collection derivedEvents)
 180  
     throws ModelException, SCXMLExpressionException {
 181  40
         State parentState = getParentState();
 182  40
         Context ctx = scInstance.getContext(parentState);
 183  40
         Evaluator eval = scInstance.getEvaluator();
 184  40
         ctx.setLocal(getNamespacesKey(), getNamespaces());
 185  
         // "location" gets preference over "name"
 186  40
         if (!SCXMLHelper.isStringEmpty(location)) {
 187  13
             Node oldNode = eval.evalLocation(ctx, location);
 188  13
             if (oldNode != null) {
 189  
                 //// rvalue may be ...
 190  
                 // a Node, if so, import it at location
 191  13
                 Node newNode = null;
 192  
                 try {
 193  13
                     if (src != null && src.trim().length() > 0) {
 194  1
                         newNode = getSrcNode();
 195  
                     } else {
 196  12
                         newNode = eval.evalLocation(ctx, expr);
 197  
                     }
 198  5
                     if (newNode != null) {
 199  
                         // adopt children, possible spec clarification needed
 200  5
                         for (Node child = newNode.getFirstChild();
 201  12
                                 child != null;
 202  7
                                 child = child.getNextSibling()) {
 203  7
                             Node importedNode = oldNode.getOwnerDocument().
 204  
                                 importNode(child, true);
 205  7
                             oldNode.appendChild(importedNode);
 206  
                         }
 207  
                     }
 208  8
                 } catch (SCXMLExpressionException see) {
 209  
                     // or something else, stuff toString() into lvalue
 210  8
                     Object valueObject = eval.eval(ctx, expr);
 211  8
                     SCXMLHelper.setNodeValue(oldNode, valueObject.toString());
 212  5
                 }
 213  13
                 if (appLog.isDebugEnabled()) {
 214  0
                     appLog.debug("<assign>: data node '" + oldNode.getNodeName()
 215  
                         + "' updated");
 216  
                 }
 217  13
                 TriggerEvent ev = new TriggerEvent(name + ".change",
 218  
                     TriggerEvent.CHANGE_EVENT);
 219  13
                 derivedEvents.add(ev);
 220  
             } else {
 221  0
                 appLog.error("<assign>: location does not point to"
 222  
                     + " a <data> node");
 223  
             }
 224  
         } else {
 225  
             // lets try "name" (usage as in Sep '05 WD, useful with <var>)
 226  27
             if (!ctx.has(name)) {
 227  0
                 errRep.onError(ErrorConstants.UNDEFINED_VARIABLE, name
 228  
                     + " = null", parentState);
 229  
             } else {
 230  27
                 Object varObj = null;
 231  27
                 if (src != null && src.trim().length() > 0) {
 232  0
                     varObj = getSrcNode();
 233  
                 } else {
 234  27
                     varObj = eval.eval(ctx, expr);
 235  
                 }
 236  27
                 ctx.set(name, varObj);
 237  27
                 if (appLog.isDebugEnabled()) {
 238  0
                     appLog.debug("<assign>: Set variable '" + name + "' to '"
 239  
                         + String.valueOf(varObj) + "'");
 240  
                 }
 241  27
                 TriggerEvent ev = new TriggerEvent(name + ".change",
 242  
                     TriggerEvent.CHANGE_EVENT);
 243  27
                 derivedEvents.add(ev);
 244  
             }
 245  
         }
 246  40
         ctx.setLocal(getNamespacesKey(), null);
 247  40
     }
 248  
 
 249  
     /**
 250  
      * Get the {@link Node} the "src" attribute points to.
 251  
      *
 252  
      * @return The node the "src" attribute points to.
 253  
      */
 254  
     private Node getSrcNode() {
 255  1
         String resolvedSrc = src;
 256  1
         if (pathResolver != null) {
 257  1
             resolvedSrc = pathResolver.resolvePath(src);
 258  
         }
 259  1
         Document doc = null;
 260  
         try {
 261  1
             doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().
 262  
                 parse(resolvedSrc);
 263  0
         } catch (Throwable t) {
 264  0
             org.apache.commons.logging.Log log = LogFactory.
 265  0
                 getLog(Assign.class);
 266  0
             log.error(t.getMessage(), t);
 267  1
         }
 268  1
         if (doc == null) {
 269  0
             return null;
 270  
         }
 271  1
         return doc.getDocumentElement();
 272  
     }
 273  
 
 274  
 }