001package org.vishia.gral.cfg; 002 003import java.io.File; 004import java.io.FileNotFoundException; 005import java.io.IOException; 006import java.io.InputStream; 007import java.text.ParseException; 008 009import org.vishia.gral.ifc.GralMngBuild_ifc; 010import org.vishia.mainCmd.MainCmd; 011import org.vishia.mainCmd.MainCmdLogging_ifc; 012import org.vishia.mainCmd.Report; 013import org.vishia.util.StringPartFromFileLines; 014import org.vishia.zbnf.ZbnfJavaOutput; 015import org.vishia.zbnf.ZbnfParser; 016 017/**Class to read the configuration script for a Graphical User Interface. The syntax of the configuration 018 * matches to the class {@link GralCfgData}, which contains all data of read configuration 019 * after invoking the read method. That configuration data are associated in 020 * {@link GralCfgBuilder#GuiCfgBuilder(GralCfgData, GralMngBuild_ifc, File)} and used in 021 * {@link GralCfgBuilder#buildGui(org.vishia.msgDispatch.LogMessage, int)} to build the GUI appearance. 022 * The building of the GUI with the {@link GralCfgData} can be done without this script reader too, 023 * but this class reads that data from a script. 024 * 025 * @author Hartmut Schorrig 026 * 027 */ 028public class GralCfgZbnf 029{ 030 031 /**Version and history 032 * <ul> 033 * <li>2018-09-17 Now the syntax is contained in <code>org/vishia/gral/cfg/Syntax.zbnf</code> as file inside jar (ressource). 034 * It is read with {@link #getSyntaxFromJar()} 035 * <li>2011-05-00 Hartmut created, the old ZbnfCfg.. class is obsolte now. 036 * </ul> 037 * 038 * <b>Copyright/Copyleft</b>:<br> 039 * For this source the LGPL Lesser General Public License, 040 * published by the Free Software Foundation is valid. 041 * It means: 042 * <ol> 043 * <li> You can use this source without any restriction for any desired purpose. 044 * <li> You can redistribute copies of this source to everybody. 045 * <li> Every user of this source, also the user of redistribute copies 046 * with or without payment, must accept this license for further using. 047 * <li> But the LPGL is not appropriate for a whole software product, 048 * if this source is only a part of them. It means, the user 049 * must publish this part of source, 050 * but doesn't need to publish the whole source of the own product. 051 * <li> You can study and modify (improve) this source 052 * for own using or for redistribution, but you have to license the 053 * modified sources likewise under this LGPL Lesser General Public License. 054 * You mustn't delete this Copyright/Copyleft inscription in this source file. 055 * </ol> 056 * If you intent to use this source without publishing its usage, you can get 057 * a second license subscribing a special contract with the author. 058 * 059 * @author Hartmut Schorrig = hartmut.schorrig@vishia.de 060 */ 061 public static final int version = 20120303; 062 063 064 private final ZbnfParser parser; 065 066 private final ZbnfJavaOutput zbnfJavaOutput; 067 068 private final MainCmdLogging_ifc console; 069 070 private final File fileSyntax; 071 072 /**The standard syntax for graphic configuration. 073 * Note: it is possible to use an abbreviated syntax with the same semantic if the constructor {@link GralCfgZbnf#GralCfgZbnf(Report, File)} is used. 074 * This syntax is used with the constructor 075 * */ 076 @Deprecated public final String XXXsyntaxStd = 077 " GuiDialogZbnfControlled::=\n" 078 + " [ size( <#?ySize> , <#?xSize> ) ;]\n" 079 + " { DataReplace: <DataReplace>\n" 080 + " | Type <Type>\n" 081 + " | if <Conditional>\n" 082 + " | <Element> \n" 083 + " } \\e.\n" 084 + "\n" 085 + "\n" 086 + "Element::=\n" 087 + "[@ <*:?positionString>:] \n" 088 + "[ Led ( <param?Led> ) ;\n" 089 + "| Button ( <param?Button> ) ; \n" 090 + "| SwitchButton ( <param?SwitchButton> ) ;\n" 091 + "| ValueBar ( <param?ValueBar> ) ;\n" 092 + "| InputTextline ( <param?InputTextline> ) ;\n" 093 + "| InputField ( <param?InputTextline> ) ;\n" 094 + "| InputBox ( <param?InputTextbox> ) ;\n" 095 + "| InputFile ( <param?InputFile> ) ;\n" 096 + "| Slider ( <param?Slider> ) ;\n" 097 + "| Show ( <param?ShowField> ) ;\n" 098 + "| <Table> \n" 099 + "| <Text> \n" 100 + "| <Imagefile>\n" 101 + "| <Line>\n" 102 + "| <Curveview>\n" 103 + "## | <InputField>\n" 104 + "| <FileInputField>\n" 105 + "].\n" 106 + "\n" 107 + "\n" 108 + "param::=\n" 109 + " { [%top<?promptPosition=t>|%t<?promptPosition=t>|%r<?promptPosition=r>] : [<\"\"?prompt> | <*,)?prompt>]xxx" 110 + " | cmd = [<\"\"?cmd>|\\[<*\\]?cmd>\\]] \n" 111 + " | text = [<\"\"?text>|<$-/?text>] \n" 112 + " | name = [<\"\"?name>|<$-/?name>] \n" 113 + " | info = [<\"\"?data>|<$-/?data>] \n" 114 + " | data = [<\"\"?data>|<*,);\\ ?data>] \n" 115 + " | action = [<\"\"?userAction>|<$-?userAction>] \n" 116 + " | show = [<\"\"?showMethod>|<$?showMethod>] \n" 117 + " | type = <$?type>\n" 118 + " | format = [<\"\"?format>|<* ,);?format>]\n" 119 + " | help = [<\"\"?help>|<* ,);?help>]\n" 120 + " ##| prompt = [<\"\"?prompt>|<* ,);?prompt>]\n" 121 + " | color = <colorName?color0> [ / <colorName?color1> ]\n" 122 + " | dropFiles = [<\"\"?dropFiles>|<$-/\\.?dropFiles>]\n" 123 + " | dropText = [<\"\"?dropText>|<$-/\\.?dropText>]\n" 124 + " | dragFiles = [<\"\"?dragFiles>|<$-/\\.?dragFiles>]\n" 125 + " | dragText = [<\"\"?dragText>|<$-/\\.?dragText>]\n" 126 + " | <\"\"?text>\n" 127 + " | <$-/\\.:?text>\n" 128 + " ##| <*,)?text>\n" 129 + " ? , \n" 130 + "}.\n" 131 + "\n" 132 + "\n" 133 + "Text::= Text ( [<\"\"?text>|<*)?text>]\n" 134 + " [ ,{ <!\\[ABC\\]?size> \n" 135 + " | <colorName> \n" 136 + " | color = <#x?colorValue> | <colorName>\n" 137 + " ? , }\n" 138 + " ]) ; .\n" 139 + "\n" 140 + "\n" 141 + "Table::=Table ( [<\"\"?text>|<*)?text>] ) :\n" 142 + "{ size ( { <#?columnWidth> ? + } x <#?height> ) \n" 143 + "| cmd = [<\"\"?cmd>|\\[<*\\]?cmd>\\]] \n" 144 + "| userAction = <$?userAction> \n" 145 + "| name = [<\"\"?name>|<$?name>] ? , \n" 146 + "} ; \n" 147 + "\n" 148 + "\n" 149 + "Curveview::=Curveview ( <$?name> [ , <#?nrofPoints>][ , active<?activate>]) :\n" 150 + "{<?line> line ( <$?name> \n" 151 + "[ , { color = [<colorName>| <#x?colorValue>] \n" 152 + " | offset = <#f?offset> \n" 153 + " | scale = <#f?scale>\n" 154 + " | data = [<\"\"?data>|<*,);\\ ?data>]\n" 155 + "| nullLine = <#?nullLine>\n" 156 + "? , } ] ) ##line-parameter\n" 157 + " ? , } ;. ##lines\n" 158 + "\n" 159 + "\n" 160 + " Imagefile::= Imagefile \n" 161 + "( { <!\\[ABCDE\\]?size>\n" 162 + "| name = <$?name>\n" 163 + "| file = <\"\"?file>|<* ,)?file>\n" 164 + "? , }\n" 165 + ") ; ." 166 + "Line::= Line ( {<colorName> | color = <#x?colorValue> |<?coord> <#f?x> , <#f?y> ? , } ) ;.\n" 167 + "?en:Line/xCoord::=\"There may be at least 2, but more possible pairs of x,y for polygons.\".\n" + 168 "colorName::=[<?color> red|green|blue|black|white|gray|brown|cyan|magenta|orange|amber|yellow|violet|purple\n" + 169 "|rd|gn|bl|gr|bn|cy|ma|or|wh|bk|ye|or|vi|pk|pu|am\n" + 170 "|lrd|lgn|lbl|lgr|lye|lor|lam|lma|lcy\n" + 171 "|prd|pgn|pbl|pgr|pye|por|pam|pma|pcy\n" + 172 "|drd|dgn|dbl|drg|dye|dor|dam|dma|dcy\n" + 173 "]\n" + 174 "\n" 175 ; 176 177 /**The current directory is that directory, where the config file is located. 178 * It is used if other files are given with relative path.*/ 179 File currentDir; 180 181 public GralCfgZbnf() 182 { this.console = MainCmd.getLogging_ifc(); 183 this.fileSyntax = null; 184 String syntax = getSyntaxFromJar(); 185 this.parser = new ZbnfParser(console); 186 try{ this.parser.setSyntax(syntax); //Std); 187 } catch(ParseException exc){ 188 throw new RuntimeException(exc); //unexpected because syntax is given here. 189 } 190 this.zbnfJavaOutput = new ZbnfJavaOutput(console); 191 } 192 193 194 public GralCfgZbnf(Report log, File fileSyntax) 195 { this.console = log; 196 this.fileSyntax = fileSyntax; 197 this.parser = new ZbnfParser(log); 198 this.zbnfJavaOutput = new ZbnfJavaOutput(log); 199 } 200 201 202 /** 203 * @return null if not found. 204 */ 205 String getSyntaxFromJar() { 206 String syntax = null; 207 ClassLoader classLoader = ClassLoader.getSystemClassLoader(); 208 //classLoader.getResource("org.vishia.gral.cfg.Syntax.txt"); 209 InputStream in = classLoader.getResourceAsStream("org/vishia/gral/cfg/Syntax.zbnf"); 210 if(in == null) return null; //not found 211 byte[] data = new byte[10000]; 212 try { 213 int nBytes; 214 do{ 215 nBytes = in.read(data); 216 String sdata = new String(data, 0, nBytes); 217 if(syntax == null) { syntax = sdata; } 218 else { syntax += sdata; } 219 } while(nBytes == data.length); 220 221 } catch (IOException e) { 222 // TODO Auto-generated catch block 223 e.printStackTrace(); 224 } 225 return syntax; 226 } 227 228 229 230 /**Configures the GUI using a description in a file. The syntax is described see {@link #configureWithZbnf(String, String)}. 231 * Because the configuration is containing in a user-accessible file, it may be faulty. 232 * Than a error message was written on the own Report output. Therefore this routine 233 * should be called after the main application is started. See example in {@link org.vishia.appl.menu.Menu}. 234 * 235 * 236 * @param sTitle Title line for the application 237 * @param fileConfigurationZbnf File containing the configuration. The file should be exist and able to read. 238 * @return true if successfully, false on any error. If false, an error message was written 239 * using the own Report-implementation. 240 */ 241 public String configureWithZbnf(File fileConfigurationZbnf, GralCfgData destination) 242 { String sError = null; 243 File dirOfconfig = fileConfigurationZbnf.getParentFile(); 244 System.out.println("GralCfgZbnf - start parse cfg file; " + fileConfigurationZbnf.getAbsolutePath()); 245 //parses the configuration file and fill the configuration data. 246 //Note: The building of the graphic appearance will be done in the graphic thread with this data later. 247 sError = ZbnfJavaOutput.parseFileAndFillJavaObject(destination.getClass(), destination 248 , fileConfigurationZbnf, fileSyntax, console, 0); 249 if(sError != null) 250 { return "Error reading config file" + sError; 251 } 252 253 254 StringPartFromFileLines spToParse = null; 255 try 256 { //spToParse = new StringPartFromFileLines(new File(sFileIn)); 257 spToParse = new StringPartFromFileLines(fileConfigurationZbnf, -1, null, null); 258 } 259 catch(FileNotFoundException exception) 260 { sError = "file not found:" + fileConfigurationZbnf.getAbsolutePath(); 261 console.writeError(sError); 262 } 263 catch(IOException exception) 264 { sError = "file read error:" + fileConfigurationZbnf.getAbsolutePath(); 265 console.writeError(sError); 266 } 267 if(spToParse != null) 268 { //sError = configureWithZbnf(sTitle, spToParse, panel, dirOfconfig); 269 spToParse.close(); //close the StringPart, it means it can't be used furthermore. 270 } 271 return sError; 272 } 273 274 275 /**Configures the GUI using a description in a file. The syntax is described see {@link #configureWithZbnf(String, String)}. 276 * Because the configuration is containing in a user-accessible file, it may be faulty. 277 * Than a error message was written on the own Report output. Therefore this routine 278 * should be called after the main application is started. See example in {@link org.vishia.appl.menu.Menu}. 279 * 280 * 281 * @param sTitle Title line for the application 282 * @param fileConfigurationZbnf File containing the configuration. The file should be exist and able to read. 283 * @return true if successfully, false on any error. If false, an error message was written 284 * using the own Report-implementation. 285 */ 286 public void configureWithZbnf(CharSequence configurationZbnf, GralCfgData destination) 287 throws ParseException 288 { //parses the configuration file and fill the configuration data. 289 //Note: The building of the graphic appearance will be done in the graphic thread with this data later. 290 boolean bOk = parser.parse(configurationZbnf.toString()); 291 if(!bOk) { 292 String sError = parser.getSyntaxErrorReport(); 293 throw new ParseException(sError, 0); 294 } 295 else { 296 try{ zbnfJavaOutput.setContent(destination.getClass(), destination, parser.getFirstParseResult()); 297 } catch(Exception exc) { 298 throw new RuntimeException(exc); //unexpected because semantic and data structure is given here. 299 } 300 } 301 } 302 303 304 305 306}