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 }