001 /*--------------------------------------------------------------------------+
002 $Id: SimulinkModelBuilder.java 26277 2010-02-18 10:46:58Z 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.builder;
019
020 import static edu.tum.cs.simulink.model.SimulinkConstants.SECTION_Library;
021 import static edu.tum.cs.simulink.model.SimulinkConstants.SECTION_Model;
022 import static edu.tum.cs.simulink.model.SimulinkConstants.SECTION_Stateflow;
023
024 import java.io.File;
025 import java.io.FileNotFoundException;
026 import java.io.FileReader;
027 import java.util.List;
028
029 import java_cup.runtime.Symbol;
030 import edu.tum.cs.commons.logging.ILogger;
031 import edu.tum.cs.simulink.model.ParameterizedElement;
032 import edu.tum.cs.simulink.model.SimulinkConstants;
033 import edu.tum.cs.simulink.model.SimulinkModel;
034
035 /**
036 * Main Simulink/Stateflow model building class.
037 *
038 * @author deissenb
039 * @author $Author: juergens $
040 * @version $Rev: 26277 $
041 * @levd.rating GREEN Hash: E704F92B0AFA17405410791609277169
042 */
043 public class SimulinkModelBuilder {
044
045 /** File to parse. */
046 private final File file;
047
048 /** Logger. */
049 private final ILogger logger;
050
051 /**
052 * Create mode builder.
053 *
054 * @param file
055 * file to parse
056 * @param logger
057 * logger for reporting anomalies. You may use SimpleLogger here.
058 */
059 public SimulinkModelBuilder(File file, ILogger logger) {
060 this.file = file;
061 this.logger = logger;
062 }
063
064 /**
065 * Build model.
066 *
067 * @return the model
068 * @throws FileNotFoundException
069 * if file was not found.
070 * @throws SimulinkModelBuildingException
071 * if a parsing error occurred.
072 */
073 public SimulinkModel buildModel() throws FileNotFoundException,
074 SimulinkModelBuildingException {
075 MDLSection simulinkFile = parseFile();
076
077 // get section that holds Simulink model to determine model name and
078 // type
079 MDLSection modelSection = getSimulinkModelSection(simulinkFile);
080 SimulinkModel model = new SimulinkModel(file, modelSection.getName()
081 .equals(SECTION_Library));
082 addParameters(model, modelSection);
083
084 // build Stateflow machine first
085 MDLSection stateflowSection = simulinkFile
086 .getFirstSubSection(SECTION_Stateflow);
087 if (stateflowSection != null) {
088 new StateflowBuilder(model, logger)
089 .buildStateflow(stateflowSection);
090 }
091
092 new SimulinkBuilder(model, logger).buildSimulink(modelSection);
093
094 return model;
095 }
096
097 /**
098 * Determine the section that holds the Simulink model. This may be
099 * {@link SimulinkConstants#SECTION_Model} or
100 * {@link SimulinkConstants#SECTION_Library}</code>.
101 *
102 * @param simulinkFile
103 * the Simulink file
104 * @throws SimulinkModelBuildingException
105 * if no or multiple {@link SimulinkConstants#SECTION_Model}/
106 * {@link SimulinkConstants#SECTION_Library}</code> were found
107 */
108 private static MDLSection getSimulinkModelSection(MDLSection simulinkFile)
109 throws SimulinkModelBuildingException {
110 List<MDLSection> namedBlocks = simulinkFile
111 .getSubSections(SECTION_Model);
112
113 if (namedBlocks.isEmpty()) {
114 namedBlocks = simulinkFile.getSubSections(SECTION_Library);
115 }
116
117 if (namedBlocks.isEmpty() || namedBlocks.size() > 1) {
118 throw new SimulinkModelBuildingException(
119 "Model must have exactly one Model or Library block.");
120 }
121
122 return namedBlocks.get(0);
123 }
124
125 /**
126 * Parse Simulink file.
127 *
128 * @throws FileNotFoundException
129 * if file was not found.
130 * @throws SimulinkModelBuildingException
131 * if an exception occurred during parsing.
132 */
133 private MDLSection parseFile() throws FileNotFoundException,
134 SimulinkModelBuildingException {
135 MDLScanner scanner = new MDLScanner(new FileReader(file));
136 MDLParser parser = new MDLParser(scanner, logger);
137 Symbol sym;
138 try {
139 sym = parser.parse();
140 } catch (Exception e) {
141 throw new SimulinkModelBuildingException(e);
142 }
143 MDLSection mdlFile = (MDLSection) sym.value;
144 return mdlFile;
145 }
146
147 /**
148 * Add all parameters defined in a section to a Simulink block. The
149 * {@link SimulinkConstants#PARAM_Points} parameter is treated specially
150 * here. This parameter stores layout information and this is merged instead
151 * of overwritten. This behavior is required to deal with the hierarchy in
152 * lines caused by branches.
153 */
154 /* package */static void addParameters(ParameterizedElement element,
155 MDLSection section) {
156 for (String name : section.getParameterNames()) {
157 // be smart for some special parameters
158 if (SimulinkConstants.PARAM_Points.equals(name)) {
159 String value = element
160 .getParameter(SimulinkConstants.PARAM_Points);
161 String newValue = section
162 .getParameter(SimulinkConstants.PARAM_Points);
163 if (value == null) {
164 value = newValue;
165 } else {
166 // prepend value
167 value = newValue.substring(0, newValue.length() - 1) + "; "
168 + value.substring(1);
169 }
170 element.setParameter(SimulinkConstants.PARAM_Points, value);
171 } else {
172 element.setParameter(name, section.getParameter(name));
173 }
174 }
175 }
176
177 }