001 /*--------------------------------------------------------------------------+
002 $Id: SimulinkModel.java 26285 2010-02-18 11:22:54Z juergens $
003 | |
004 | Copyright 2005-2010 Technische Universitaet Muenchen |
005 | |
006 | Licensed under the Apache License, Version 2.0 (the "License"); |
007 | you may not use this file except in compliance with the License. |
008 | You may obtain a copy of the License at |
009 | |
010 | http://www.apache.org/licenses/LICENSE-2.0 |
011 | |
012 | Unless required by applicable law or agreed to in writing, software |
013 | distributed under the License is distributed on an "AS IS" BASIS, |
014 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
015 | See the License for the specific language governing permissions and |
016 | limitations under the License. |
017 +--------------------------------------------------------------------------*/
018 package edu.tum.cs.simulink.model;
019
020 import java.io.File;
021 import java.util.HashMap;
022 import java.util.HashSet;
023 import java.util.List;
024 import java.util.Set;
025
026 import edu.tum.cs.commons.assertion.CCSMPre;
027 import edu.tum.cs.commons.assertion.PreconditionException;
028 import edu.tum.cs.commons.clone.DeepCloneException;
029 import edu.tum.cs.commons.collections.CollectionUtils;
030 import edu.tum.cs.commons.collections.TwoDimHashMap;
031 import edu.tum.cs.commons.collections.UnmodifiableSet;
032 import edu.tum.cs.simulink.model.stateflow.StateflowBlock;
033 import edu.tum.cs.simulink.model.stateflow.StateflowChart;
034 import edu.tum.cs.simulink.model.stateflow.StateflowMachine;
035 import edu.tum.cs.simulink.util.SimulinkUtils;
036
037 /**
038 * A Simulink model a specialized Simulink block that primarily maintains the
039 * default parameters of blocks, annotations and lines. See the
040 * {@linkplain edu.tum.cs.simulink.model package documentation} for details on
041 * the parameter mechanism.
042 *
043 * @author hummelb
044 * @author $Author: juergens $
045 * @version $Rev: 26285 $
046 * @levd.rating GREEN Hash: 3CF95158690744EE5981BAF8E395EE3F
047 */
048 public class SimulinkModel extends SimulinkBlock {
049
050 /**
051 * Block parameter defaults. This maps from (block type x parameter name) to
052 * parameter value.
053 */
054 private final TwoDimHashMap<String, String, String> blockTypeDefaultParams = new TwoDimHashMap<String, String, String>();
055
056 /**
057 * Block parameter defaults. This maps from parameter name to parameter
058 * value.
059 */
060 private final HashMap<String, String> blockDefaultParams = new HashMap<String, String>();
061
062 /**
063 * Annotation parameter defaults. This maps from parameter name to parameter
064 * value.
065 */
066 private final HashMap<String, String> annotationDefaultsParams = new HashMap<String, String>();
067
068 /**
069 * Line parameter defaults. This maps from parameter name to parameter
070 * value.
071 */
072 private final HashMap<String, String> lineDefaultParams = new HashMap<String, String>();
073
074 /** The file this model is stored in. */
075 private final File file;
076
077 /** Flag marks libraries. */
078 private final boolean isLibrary;
079
080 /** Stateflow machine of this model. May be <code>null</code>. */
081 private StateflowMachine stateflowMachine;
082
083 /**
084 * Create new model.
085 *
086 * @param file
087 * the file this model is stored in
088 */
089 public SimulinkModel(File file, boolean isLibrary) {
090 this.file = file;
091 this.isLibrary = isLibrary;
092 }
093
094 /** This copy constructor clones the whole model. */
095 protected SimulinkModel(SimulinkModel origModel) throws DeepCloneException {
096 super(origModel);
097 file = origModel.file;
098 isLibrary = origModel.isLibrary;
099
100 // Clone type-specific block parameter defaults
101 blockTypeDefaultParams.putAll(origModel.blockTypeDefaultParams);
102
103 // Clone block parameter defaults
104 blockDefaultParams.putAll(origModel.blockDefaultParams);
105
106 // Clone annotation parameter defaults
107 annotationDefaultsParams.putAll(origModel.annotationDefaultsParams);
108
109 // Clone line parameter defaults
110 lineDefaultParams.putAll(origModel.lineDefaultParams);
111
112 // Clone machine
113 if (origModel.stateflowMachine != null) {
114 stateflowMachine = new StateflowMachine(origModel.stateflowMachine,
115 this);
116 for (StateflowChart chart : origModel.stateflowMachine.getCharts()) {
117 createLink(chart);
118 }
119 }
120 }
121
122 /** Set annotation default parameter. */
123 public void setAnnotationDefaultParameter(String name, String value) {
124 annotationDefaultsParams.put(name, value);
125 }
126
127 /**
128 * Set a default parameter for all blocks.
129 */
130 public void setBlockDefaultParameter(String name, String value) {
131 blockDefaultParams.put(name, value);
132 }
133
134 /**
135 * Set default parameter for blocks of a specified type.
136 */
137 public void setBlockTypeDefaultParameter(String type, String name,
138 String value) {
139 blockTypeDefaultParams.putValue(type, name, value);
140 }
141
142 /** Set default parameter for lines. */
143 public void setLineDefaultParameter(String name, String value) {
144 lineDefaultParams.put(name, value);
145 }
146
147 /** Deep clone this model. */
148 @Override
149 public SimulinkModel deepClone() throws DeepCloneException {
150 return new SimulinkModel(this);
151 }
152
153 /** Get default annotation parameter. */
154 public String getAnnotationDefaultParameter(String name) {
155 return annotationDefaultsParams.get(name);
156 }
157
158 /** Get names of annotation default parameters. */
159 public UnmodifiableSet<String> getAnnotationDefaultParameterNames() {
160 return CollectionUtils
161 .asUnmodifiable(annotationDefaultsParams.keySet());
162 }
163
164 /**
165 * Get a block specified by its full qualified name. The name must start
166 * with the models name. This returns <code>null</code> if the block was
167 * not found.
168 */
169 public SimulinkBlock getBlock(String id) {
170
171 List<String> names = SimulinkUtils.splitSimulinkId(id);
172
173 // if the the first name is not the models name, return null (ensure
174 // there is a first before)
175 if (names.isEmpty() || !names.get(0).equals(getName())) {
176 return null;
177 }
178
179 SimulinkBlock block = this;
180
181 for (int i = 1; i < names.size(); i++) {
182 // names are unormalized
183 block = block.getSubBlock(names.get(i));
184 if (block == null) {
185 return null;
186 }
187 }
188
189 return block;
190 }
191
192 /**
193 * Get block default parameter.
194 */
195 public String getBlockDefaultParameter(String name) {
196 return blockDefaultParams.get(name);
197 }
198
199 /**
200 * Get named default parameter for a given type. If a type-specific
201 * parameter is defined, it is returned. Otherwise the block default ({@link #getBlockDefaultParameter(String)})
202 * is returned.
203 */
204 public String getTypeBlockDefaultParameter(String type, String name) {
205 String value = blockTypeDefaultParams.getValue(type, name);
206 if (value == null) {
207 return getBlockDefaultParameter(name);
208 }
209 return value;
210 }
211
212 /**
213 * Get names of block default parameters.
214 */
215 public UnmodifiableSet<String> getBlockDefaultParameterNames() {
216 return CollectionUtils.asUnmodifiable(blockDefaultParams.keySet());
217 }
218
219 /**
220 * Get all default parameter names for a given type. This includes the block
221 * defaults ({@link #getBlockDefaultParameterNames()}).
222 */
223 public Set<String> getBlockDefaultParameterNames(String type) {
224 HashSet<String> parameterNames = new HashSet<String>();
225 parameterNames.addAll(blockTypeDefaultParams.getSecondKeys(type));
226 parameterNames.addAll(blockDefaultParams.keySet());
227 return parameterNames;
228 }
229
230 /** Returns the name of the model. */
231 @Override
232 public String getId() {
233 return SimulinkUtils.escape(getName());
234 }
235
236 /** Get default line parameter. */
237 public String getLineDefaultParameter(String name) {
238 return lineDefaultParams.get(name);
239 }
240
241 /** Get default line parameter names. */
242 public UnmodifiableSet<String> getLineDefaultParameterNames() {
243 return CollectionUtils.asUnmodifiable(lineDefaultParams.keySet());
244 }
245
246 /** Returns itself. */
247 @Override
248 public SimulinkModel getModel() {
249 return this;
250 }
251
252 /**
253 * Get Stateflow machine of this model (may be <code>null</code>).
254 */
255 public StateflowMachine getStateflowMachine() {
256 return stateflowMachine;
257 }
258
259 /** Returns {@link SimulinkConstants#TYPE_Model}. */
260 @Override
261 public String getType() {
262 return SimulinkConstants.TYPE_Model;
263 }
264
265 /** Is this model a library? */
266 public boolean isLibrary() {
267 return isLibrary;
268 }
269
270 /**
271 * Set Stateflow machine. This is not expected to be called by the user, but
272 * only by the constructors of {@link StateflowMachine}.
273 *
274 * @throws PreconditionException
275 * if this model already has a machine of if the machine does
276 * not belong to this model.
277 */
278 public void setStateflowMachine(StateflowMachine machine) {
279 if (machine != null) {
280 CCSMPre.isTrue(stateflowMachine == null,
281 "This model already has a Stateflow machine.");
282 CCSMPre
283 .isTrue(machine.getModel() == this,
284 "Can be called only for the machine that belongs to this model");
285 }
286
287 stateflowMachine = machine;
288 }
289
290 /** Create line between chart and Stateflow block (during deep cloning). */
291 private void createLink(StateflowChart origChart) {
292 StateflowBlock block = (StateflowBlock) getBlock(origChart
293 .getStateflowBlock().getId());
294 StateflowChart cloneChart = block.getChart();
295 stateflowMachine.addChart(block.getId(), cloneChart);
296 }
297
298 /**
299 * This throws a {@link UnsupportedOperationException} as models cannot have
300 * parents.
301 */
302 @Override
303 protected void setParent(SimulinkBlock parent) {
304 throw new UnsupportedOperationException("Models cannot have parents.");
305 }
306
307 }