001/*
002 * Copyright (c) 1998-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: welker $'
006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 
007 * '$Revision: 24234 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.geon;
031
032import java.io.ByteArrayInputStream;
033import java.io.InputStream;
034import java.util.Map;
035import java.util.Set;
036
037import javax.xml.parsers.DocumentBuilder;
038import javax.xml.parsers.DocumentBuilderFactory;
039
040import org.w3c.dom.Document;
041import org.w3c.dom.Element;
042import org.w3c.dom.NodeList;
043
044import ptolemy.actor.TypedAtomicActor;
045import ptolemy.actor.TypedIOPort;
046import ptolemy.data.ArrayToken;
047import ptolemy.data.DoubleToken;
048import ptolemy.data.StringToken;
049import ptolemy.data.Token;
050import ptolemy.data.expr.ASTPtRootNode;
051import ptolemy.data.expr.ModelScope;
052import ptolemy.data.expr.ParseTreeEvaluator;
053import ptolemy.data.expr.PtParser;
054import ptolemy.data.type.ArrayType;
055import ptolemy.data.type.BaseType;
056import ptolemy.data.type.Type;
057import ptolemy.data.type.TypeConstant;
058import ptolemy.kernel.CompositeEntity;
059import ptolemy.kernel.util.IllegalActionException;
060import ptolemy.kernel.util.NameDuplicationException;
061
062//////////////////////////////////////////////////////////////////////////
063//// Expression
064/**
065 * Get 2D classification point for rock classification.
066 * 
067 * The actor Accepts coordinates expressions and an xml composition string. It
068 * evaluates the expression using the expression evaluator (PtParser as in the
069 * Expression actor) and the composition. Returns an array of doubles of length
070 * two representing the x and y values.
071 * 
072 * see Expression // is ambiguous
073 * 
074 * @author Efrat Jaeger
075 * @version $Id: Get2DPoint.java 24234 2010-05-06 05:21:26Z welker $
076 * @since Ptolemy II 4.0.1
077 */
078
079public class Get2DPoint extends TypedAtomicActor {
080
081        /**
082         * Construct an actor with the given container and name.
083         * 
084         * @param container
085         *            The container.
086         * @param name
087         *            The name of this actor.
088         * @exception IllegalActionException
089         *                If the actor cannot be contained by the proposed
090         *                container.
091         * @exception NameDuplicationException
092         *                If the container already has an actor with this name.
093         */
094        public Get2DPoint(CompositeEntity container, String name)
095                        throws NameDuplicationException, IllegalActionException {
096                super(container, name);
097
098                rowInfo = new TypedIOPort(this, "rowInfo", true, false);
099                rowInfo.setTypeEquals(BaseType.STRING);
100
101                coordinates = new TypedIOPort(this, "coordinates", true, false);
102                coordinates.setTypeEquals(new ArrayType(BaseType.STRING));
103
104                point = new TypedIOPort(this, "point", false, true);
105                point.setTypeEquals(new ArrayType(BaseType.DOUBLE));
106        }
107
108        // /////////////////////////////////////////////////////////////////
109        // // ports and parameters ////
110
111        /** Composition info. */
112        public TypedIOPort rowInfo;
113
114        /**
115         * An array of the coordinates to be evaluated.
116         */
117        public TypedIOPort coordinates;
118
119        /**
120         * The classification point.
121         */
122        public TypedIOPort point;
123
124        // /////////////////////////////////////////////////////////////////
125        // // public methods ////
126
127        /**
128         * Accepts coordinates expressions and an xml composition string. Evaluates
129         * the expression using the expression evaluator and the composition.
130         * Returns an array of doubles of length two representing the x and y
131         * values.
132         * 
133         * @exception IllegalActionException
134         *                If the evaluation of the expression triggers it, or the
135         *                evaluation yields a null result, or the evaluation yields
136         *                an incompatible type, or if there is no director, or if a
137         *                connected input has no tokens.
138         */
139        public void fire() throws IllegalActionException {
140
141                try {
142                        Token[] coordinatesTokens = ((ArrayToken) coordinates.get(0))
143                                        .arrayValue();
144
145                        String compositionXML = ((StringToken) rowInfo.get(0))
146                                        .stringValue();
147                        try {
148                                DocumentBuilderFactory factory = DocumentBuilderFactory
149                                                .newInstance();
150                                factory.setValidating(false);
151                                DocumentBuilder builder = factory.newDocumentBuilder();
152                                byte[] xmlBytes = compositionXML.getBytes();
153                                InputStream is = new ByteArrayInputStream(xmlBytes);
154                                _composition = builder.parse(is);
155                        } catch (Exception ex) {
156                                throw new IllegalActionException(this, ex
157                                                + " xml processing exception.");
158                        }
159
160                        String xCoor = ((StringToken) coordinatesTokens[1]).stringValue();
161                        String yCoor = ((StringToken) coordinatesTokens[2]).stringValue();
162
163                        // Token inputToken = port.get(0);
164                        // _tokenMap.put(port.getName(), inputToken);
165
166                        PtParser parser = new PtParser();
167                        _parseTree = parser.generateParseTree(xCoor);
168                        _parseTreeEvaluator = new ParseTreeEvaluator();
169                        _scope = new VariableScope();
170                        DoubleToken xToken = (DoubleToken) _parseTreeEvaluator
171                                        .evaluateParseTree(_parseTree, _scope);
172                        _parseTree = parser.generateParseTree(yCoor);
173                        DoubleToken yToken = (DoubleToken) _parseTreeEvaluator
174                                        .evaluateParseTree(_parseTree, _scope);
175                        if (xToken == null || yToken == null) {
176                                throw new IllegalActionException(this,
177                                                "One of the coordinates yields a null result: "
178                                                                + " x : " + xCoor + " , y : " + yCoor);
179                        }
180
181                        double xVal = xToken.doubleValue();
182                        double yVal = yToken.doubleValue();
183                        Token arrayToken[] = new Token[2];
184                        arrayToken[0] = new DoubleToken(xVal);
185                        arrayToken[1] = new DoubleToken(yVal);
186                        // Point2D.Double _point = new Point2D.Double(xVal, yVal);
187                        point.broadcast(new ArrayToken(arrayToken));
188                } catch (IllegalActionException ex) {
189                        // Chain exceptions to get the actor that threw the exception.
190                        throw new IllegalActionException(this, ex,
191                                        "Invalid coordintes expression.");
192                }
193
194        }
195
196        // /////////////////////////////////////////////////////////////////
197        // // private methods ////
198
199        private class VariableScope extends ModelScope {
200
201                /**
202                 * Look up and return the attribute with the specified name in the
203                 * scope. Return 0 if such an attribute does not exist.
204                 * 
205                 * @return The attribute with the specified name in the scope.
206                 */
207                public Token get(String name) throws IllegalActionException {
208
209                        String strVal = "";
210                        double value = 0;
211                        NodeList minValues = _composition.getElementsByTagName(name);
212                        for (int i = 0; i < minValues.getLength(); i++) {
213                                Element mineral = (Element) minValues.item(i);
214                                if (mineral.getChildNodes().getLength() > 0) {
215                                        strVal = mineral.getFirstChild().getNodeValue().trim();
216                                }
217                                if (!strVal.equals("")) {
218                                        Double DVal = new Double(Double.parseDouble(strVal));
219                                        value = DVal.doubleValue();
220                                }
221                        }
222                        return new DoubleToken(value);
223                }
224
225                /**
226                 * Look up and return the type of the attribute with the specified name
227                 * in the scope. Return null if such an attribute does not exist.
228                 * 
229                 * @return The attribute with the specified name in the scope.
230                 */
231                public Type getType(String name) throws IllegalActionException {
232                        return BaseType.DOUBLE;
233                }
234
235                /**
236                 * Look up and return the type term for the specified name in the scope.
237                 * Return null if the name is not defined in this scope, or is a
238                 * constant type.
239                 * 
240                 * @return The InequalityTerm associated with the given name in the
241                 *         scope.
242                 * @exception IllegalActionException
243                 *                If a value in the scope exists with the given name,
244                 *                but cannot be evaluated.
245                 */
246                public ptolemy.graph.InequalityTerm getTypeTerm(String name)
247                                throws IllegalActionException {
248                        return new TypeConstant(BaseType.DOUBLE);
249                }
250
251                /**
252                 * Return the list of identifiers within the scope.
253                 * 
254                 * @return The list of identifiers within the scope.
255                 */
256                public Set identifierSet() {
257                        return getAllScopedVariableNames(null, Get2DPoint.this);
258                }
259        }
260
261        // /////////////////////////////////////////////////////////////////
262        // // private variables ////
263
264        private Document _composition = null;
265        private int _iterationCount = 1;
266        private ASTPtRootNode _parseTree = null;
267        private ParseTreeEvaluator _parseTreeEvaluator = null;
268        private VariableScope _scope = null;
269        private Map _tokenMap;
270}