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

Classes in this File Line Coverage Branch Coverage Complexity
Assign
84% 
90% 
1.923

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