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 }