001/*
002 * Copyright (c) 2004-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.sdm.spa;
031
032import java.util.StringTokenizer;
033import java.util.Vector;
034
035import ptolemy.actor.TypedAtomicActor;
036import ptolemy.actor.TypedIOPort;
037import ptolemy.data.BooleanToken;
038import ptolemy.data.StringToken;
039import ptolemy.data.expr.Parameter;
040import ptolemy.data.type.BaseType;
041import ptolemy.kernel.CompositeEntity;
042import ptolemy.kernel.util.IllegalActionException;
043import ptolemy.kernel.util.NameDuplicationException;
044
045//////////////////////////////////////////////////////////////////////////
046//// Extract Item
047/**
048 * This Actor will extract items from an XML document. for now it will only
049 * extract the first item.
050 * 
051 * @param input
052 *            : The string that contains the XML content
053 * @param xpath
054 *            : The xpath for the item to be extracted.
055 */
056
057public class EnumItemTriggered extends TypedAtomicActor {
058
059        /**
060         * Construct a constant source with the given container and name. Create the
061         * <i>value</i> parameter, initialize its value to the default value of an
062         * IntToken with value 1.
063         * 
064         * @param container
065         *            The container.
066         * @param name
067         *            The name of this actor.
068         * @exception IllegalActionException
069         *                If the entity cannot be contained by the proposed
070         *                container.
071         * @exception NameDuplicationedException
072         *                If the container already has an actor with this name.
073         * 
074         */
075        public EnumItemTriggered(CompositeEntity container, String name)
076                        throws NameDuplicationException, IllegalActionException {
077                super(container, name);
078                // super(container, name);
079                xpath = new Parameter(this, "xpath", new StringToken(""));
080
081                endOfLoop = new TypedIOPort(this, "endOfLoop", false, true);
082                endOfLoop.setTypeEquals(BaseType.BOOLEAN);
083                output = new TypedIOPort(this, "output", false, true);
084                output.setTypeEquals(BaseType.STRING);
085
086                input = new TypedIOPort(this, "input", true, false);
087                input.setTypeEquals(BaseType.STRING);
088                branchFinished = new TypedIOPort(this, "branchFinished", true, false);
089                branchFinished.setTypeEquals(BaseType.BOOLEAN);
090
091                _attachText("_iconDescription", "<svg>\n" + "<rect x=\"0\" y=\"0\" "
092                                + "width=\"60\" height=\"30\" " + "style=\"fill:white\"/>\n"
093                                + "</svg>\n");
094        }
095
096        // /////////////////////////////////////////////////////////////////
097        // // ports and parameters ////
098
099        /**
100         * The value produced by this constant source. By default, it contains an
101         * IntToken with value 1. If the type of this token is changed during the
102         * execution of a model, then the director will be asked to redo type
103         * resolution.
104         */
105        public Parameter xpath;
106        public TypedIOPort input;
107        public TypedIOPort output;
108        public TypedIOPort endOfLoop;
109        public TypedIOPort branchFinished;
110
111        // /////////////////////////////////////////////////////////////////
112        // // public methods ////
113
114        /**
115         * Clone the actor into the specified workspace. This calls the base class
116         * and then sets the value public variable in the new object to equal the
117         * cloned parameter in that new object.
118         * 
119         * @param workspace
120         *            The workspace for the new object.
121         * @return A new actor.
122         * @exception CloneNotSupportedException
123         *                If a derived class contains an attribute that cannot be
124         *                cloned.
125         */
126        /*
127         * public Object clone(Workspace workspace) throws
128         * CloneNotSupportedException { Const newObject = (Const)
129         * super.clone(workspace); // Set the type constraint.
130         * newObject.output.setTypeAtLeast(newObject.value); return newObject; }
131         */
132
133        /**
134         * Post fire the actor. Return false to indicated that the process has
135         * finished. If it returns true, the process will continue indefinitely.
136         */
137        public boolean postfire() throws IllegalActionException {
138                if (_reachedEND) {
139                        endOfLoop.broadcast(BooleanToken.TRUE);
140                        return true;
141                }
142                // endOfLoop.broadcast(BooleanToken.FALSE);
143                return true;
144        }
145
146        /**
147         * Send the token in the <i>value</i> parameter to the output.
148         * 
149         * @exception IllegalActionException
150         *                If it is thrown by the send() method sending out the
151         *                token.
152         */
153        public void fire() throws IllegalActionException {
154                p_input = ((StringToken) (input.get(0))).stringValue();
155                p_xpath = ((StringToken) (xpath.getToken())).stringValue();
156                // Now we need to extract the first item from the
157                // XML content;
158                _debug(" Broadcast:Input:" + p_input + ":" + p_xpath);
159                Vector items;
160                XMLUtil xmlutil = new XMLUtil();
161                if (p_xpath.startsWith("/")) {
162                        items = xmlutil.getItems(p_input, p_xpath);
163                } else {
164                        items = getStrItems(p_input, p_xpath);
165                }
166                String item;
167
168                for (int i = 0; i < items.size(); i++) {
169                        item = (String) items.elementAt(i);
170                        if (item.length() > 0) {
171                                _debug(" Broadcast:Process Item:" + item);
172                                output.broadcast(new StringToken(item));
173                                boolean tg = ((BooleanToken) branchFinished.get(0))
174                                                .booleanValue();
175                                if (tg)
176                                        _debug("EnumItemTriggered:Got branch finished trigger.");
177                        }
178                        // Wait for the trigger to come back.
179
180                        /*
181                         * //now wait for the return trigger //while (true) { boolean tg =
182                         * ((BooleanToken) branchFinished.get(0)).booleanValue(); if (tg) {
183                         * _debug(" Broadcast:Branching finished in Enum:" + item); //break;
184                         * } else { try { Thread.currentThread().wait(100); } catch
185                         * (InterruptedException e) { e.printStackTrace(); } }
186                         */
187                        // }
188                }
189                // endOfLoop.broadcast(new IntToken(items.size()));
190                _reachedEND = true;
191        }
192
193        private Vector getStrItems(String input, String xpath) {
194                Vector result = new Vector();
195                StringTokenizer st = new StringTokenizer(input, xpath);
196                while (st.hasMoreElements()) {
197                        String token = st.nextToken();
198                        if (token.trim().length() > 0)
199                                result.add(token.trim());
200                }
201
202                return result;
203        }
204
205        private String p_input;
206        private String p_xpath;
207
208        /** Indicator that we have reached the end of file. */
209        private boolean _reachedEND = false;
210
211}