001/* Utilities that manipulate a model. 002 003 Copyright (c) 2004-2014 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.actor.lib.hoc; 029 030import java.net.URL; 031 032import ptolemy.actor.CompositeActor; 033import ptolemy.actor.Manager; 034import ptolemy.data.RecordToken; 035import ptolemy.data.Token; 036import ptolemy.data.expr.Variable; 037import ptolemy.kernel.util.Attribute; 038import ptolemy.kernel.util.IllegalActionException; 039import ptolemy.kernel.util.KernelException; 040import ptolemy.kernel.util.NamedObj; 041import ptolemy.kernel.util.Settable; 042import ptolemy.moml.MoMLParser; 043 044/////////////////////////////////////////////////////////////////// 045//// ModelUtilities 046 047/** 048 A collection of utilities for manipulating a Ptolemy model. 049 FIXME: Currently there is only one major operation for invoke 050 the execution of a model. We may add more later. 051 052 @author Yang Zhao 053 @version $Id$ 054 @since Ptolemy II 4.1 055 @Pt.ProposedRating Yellow (eal) 056 @Pt.AcceptedRating Red (cxh) 057 */ 058public class ModelUtilities { 059 /** Instances of this class cannot be created. 060 */ 061 private ModelUtilities() { 062 } 063 064 /////////////////////////////////////////////////////////////////// 065 //// public methods //// 066 067 /** 068 * This method takes a url specifying the model to be execute. The 069 * <i>args</i> argument is a record token that will be used to set 070 * corresponding attributes of the specified model by 071 * naming match, (see _setAttribute() method). The results of 072 * executing the model is returned back by setting the value of some 073 * Attributes. In particular, only Attributes 074 * that have name matches the <i>resultLabels</i> are returned. 075 * The return result is a RecordToken which has the resultLabels as 076 * its field. 077 * @param url The Model url. 078 * @param args A set of attributes of the specified model. 079 * @param resultLabels Labels of the returned result. 080 * @return The execution result. 081 * @exception IllegalActionException If can not parse the url 082 * or failed to execute the model. 083 */ 084 public static synchronized RecordToken executeModel(URL url, 085 RecordToken args, String[] resultLabels) 086 throws IllegalActionException { 087 if (url != null) { 088 MoMLParser parser = new MoMLParser(); 089 NamedObj model; 090 091 try { 092 model = parser.parse(null, url); 093 } catch (Exception ex) { 094 throw new IllegalActionException( 095 ex + "Failed to pass the model URL." + url.toString()); 096 } 097 098 if (model instanceof CompositeActor) { 099 return executeModel((CompositeActor) model, args, resultLabels); 100 } else { 101 return null; 102 } 103 } else { 104 return null; 105 } 106 } 107 108 /** 109 * This method takes model argument which is type of CompositeActor. 110 * The <i>args</i> argument is a record token that will be used to 111 * set corresponding attributes of the specified model by 112 * naming match, (see _setAttribute() method). The results of 113 * executing the model is returned back by setting the value of some 114 * Attributes. In particular, only Attributes 115 * that have name matches the <i>resultLabels</i> are returned. 116 * The return result is a RecordToken which has the resultLabels as 117 * its field. 118 * @param model The Model. 119 * @param args A set of attributes of the specified model. 120 * @param resultLabels Labels of the returned result. 121 * @return The execution result. 122 * @exception IllegalActionException If failed to execute the model. 123 */ 124 public static synchronized RecordToken executeModel(CompositeActor model, 125 RecordToken args, String[] resultLabels) 126 throws IllegalActionException { 127 Manager manager = model.getManager(); 128 129 if (manager == null) { 130 //System.out.println("create manager for the model"); 131 manager = new Manager(model.workspace(), "Manager"); 132 model.setManager(manager); 133 } 134 135 _setAttribute(model, args); 136 137 try { 138 manager.execute(); 139 } catch (KernelException ex) { 140 throw new IllegalActionException(ex + "Execution failed."); 141 } 142 143 return _getResult(model, resultLabels); 144 } 145 146 /////////////////////////////////////////////////////////////////// 147 //// private methods //// 148 149 /** Iterate over the labelSet of the <i>args</i> argument and 150 * check whether the specified model has Attribute with the 151 * same name of a label. If so, set the value of the attribute 152 * to be the value of that record field. 153 * @exception IllegalActionException If reading the ports or 154 * setting the parameters causes it. 155 */ 156 private static void _setAttribute(CompositeActor model, RecordToken args) 157 throws IllegalActionException { 158 Object[] labels = args.labelSet().toArray(); 159 int length = args.length(); 160 161 //String[] labels = new String[length]; 162 //Token[] values = new Token[length]; 163 for (int i = 0; i < length; i++) { 164 String label = (String) labels[i]; 165 Attribute attribute = model.getAttribute(label); 166 167 // Use the token directly rather than a string if possible. 168 if (attribute != null) { 169 Token token = args.get(label); 170 171 if (attribute instanceof Variable) { 172 ((Variable) attribute).setToken(token); 173 } else if (attribute instanceof Settable) { 174 ((Settable) attribute).setExpression(token.toString()); 175 } 176 } 177 } 178 } 179 180 /** Iterate over the resultLabels and 181 * check whether the specified model has Attribute with the 182 * same name of a label. If so, get the value of the attribute 183 * and return a record token with labels equal to resultLabels 184 * and values equal to the corresponding attribute value. 185 * @param model The model executed. 186 * @param resultLabels Labels of the returned result. 187 * @return The execution result. 188 * @exception IllegalActionException If reading the ports or 189 * setting the parameters causes it. 190 */ 191 private static RecordToken _getResult(CompositeActor model, 192 String[] resultLabels) throws IllegalActionException { 193 Token[] value = new Token[resultLabels.length]; 194 195 for (int i = 0; i < resultLabels.length; i++) { 196 String label = resultLabels[i]; 197 Attribute attribute = model.getAttribute(label); 198 199 if (attribute instanceof Variable) { 200 value[i] = ((Variable) attribute).getToken(); 201 } 202 } 203 204 return new RecordToken(resultLabels, value); 205 } 206}