View Javadoc
1   package org.djunits.generator;
2   
3   import java.io.BufferedReader;
4   import java.io.File;
5   import java.io.FileNotFoundException;
6   import java.io.FileReader;
7   import java.io.PrintWriter;
8   import java.net.URISyntaxException;
9   import java.net.URL;
10  
11  /**
12   * GenerateXSD makes an XSD file for all choices possible with the units, using the textual representations. <br>
13   * <br>
14   * Copyright (c) 2003-2018 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
15   * for project information <a href="https://www.simulation.tudelft.nl/" target="_blank">www.simulation.tudelft.nl</a>. The
16   * source code and binary code of this software is proprietary information of Delft University of Technology.
17   * @author <a href="https://www.tudelft.nl/averbraeck" target="_blank">Alexander Verbraeck</a>
18   */
19  public class GenerateXSD
20  {
21      /** The output folder of the writer -- will be written in Eclipse project-root/generated-code/org/djunits folder. */
22      private static final String generatedCodeRelativePath = "/generated-code/";
23  
24      /**
25       * The calculated absolute output path (root of the executable or Jar file). In case of an Eclipse run, ../../ is added to
26       * the path to place the results in the root of the project, rather than in target/classes.
27       */
28      private static String absoluteRootPath;
29  
30      /*-
31       * DurationUnit.ms = ms  | millisecond
32         DurationUnit.s  = s   | second
33         DurationUnit.m  = min | minute | min | m
34       */
35      public static void main(final String[] args) throws FileNotFoundException
36      {
37          makeAbsolutePath();
38          makeXsd();
39          // makeAdapters();
40      }
41  
42      /** */
43      private static void makeXsd()
44      {
45          try
46          {
47              File in = new File(absoluteRootPath + "../../djunits/src/main/resources/localeunit.properties");
48              if (!in.exists())
49              {
50                  throw new RuntimeException("cannot find file " + in.getPath());
51              }
52              BufferedReader br = new BufferedReader(new FileReader(in));
53  
54              File outPath = new File(absoluteRootPath + "/resources");
55              outPath.mkdirs();
56              PrintWriter pw = new PrintWriter(absoluteRootPath + "/resources/djunits.xsd");
57              pw.write(
58                      "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <xsd:schema targetNamespace=\"http://www.djunits.org/djunits\"\n");
59              pw.write("  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n");
60              pw.write("  xmlns:djunits=\"http://www.djunits.org/djunits\"\n");
61              pw.write("  xmlns=\"http://www.djunits.org/djunits\" elementFormDefault=\"qualified\">\n");
62              pw.write("\n");
63              pw.write("  <!-- ========================================================================================= -->\n");
64              pw.write("  <!-- ===================================== DJUNITS TYPES ===================================== -->\n");
65              pw.write("  <!-- ========================================================================================= -->\n");
66              pw.write("\n");
67  
68              String typeStr = "";
69              String line = br.readLine();
70              while (line != null)
71              {
72                  if (line.startsWith("#"))
73                  {
74                      line = br.readLine();
75                      continue;
76                  }
77  
78                  if (line.contains("="))
79                  {
80                      /*-
81                         <xsd:simpleType name="SPEEDTYPE"> 
82                           <xsd:restriction base="xsd:string">
83                             <xsd:pattern value="\d+\.?\d*\s*(km/h|m/s|mi/h|ft/s)"></xsd:pattern>
84                           </xsd:restriction>
85                         </xsd:simpleType>
86                       */
87  
88                      String key = line.split("=")[0].trim().split("\\.")[0];
89                      String val = line.split("=")[1].trim();
90                      String[] vals = val.split("\\|");
91                      if (!typeStr.equals(key))
92                      {
93                          // new type
94                          if (typeStr.length() > 0)
95                          {
96                              if (typeStr.startsWith("Dimension"))
97                                  pw.write("\"></xsd:pattern>\n" + "    </xsd:restriction>\n" + "  </xsd:simpleType>\n\n");
98                              else
99                                  pw.write(")\"></xsd:pattern>\n" + "    </xsd:restriction>\n" + "  </xsd:simpleType>\n\n");
100                         }
101                         typeStr = key;
102                         String type = key.replace("Unit", "TYPE").toUpperCase();
103                         pw.write("  <xsd:simpleType name=\"" + type + "\">\n");
104                         pw.write("     <xsd:restriction base=\"xsd:string\">\n");
105                         if (type.equals("DIMENSIONLESSTYPE"))
106                             pw.write("      <xsd:pattern value=\"[+-]?\\d+\\.?\\d*\\s*");
107                         else
108                         {
109                             pw.write("      <xsd:pattern value=\"[+-]?\\d+\\.?\\d*\\s*(");
110                             if (vals.length > 2)
111                             {
112                                 pw.write(escape(vals[2]));
113                                 for (int i = 3; i < vals.length; i++)
114                                     pw.write("|" + escape(vals[i]));
115                             }
116                             else
117                                 pw.write(escape(vals[0]));
118                         }
119                     }
120                     else
121                     {
122                         if (vals.length > 2)
123                         {
124                             for (int i = 2; i < vals.length; i++)
125                                 pw.write("|" + escape(vals[i]));
126                         }
127                         else
128                             pw.write("|" + escape(vals[0]));
129                     }
130                     System.out.println(vals[0]);
131                 }
132                 line = br.readLine();
133             }
134             if (typeStr.length() > 0)
135             {
136                 pw.write(")\"></xsd:pattern>\n" + "    </xsd:restriction>\n" + "  </xsd:simpleType>\n\n" + "</xsd:schema>\n");
137             }
138             pw.close();
139             br.close();
140 
141             System.out.println("built: " + absoluteRootPath + "/resources/djunits.xsd");
142 
143         }
144         catch (Exception exception)
145         {
146             exception.printStackTrace();
147         }
148     }
149 
150     /** the characters to escape. */
151     private static final String escape = "(){}.?|<>*-+'\\%^";
152 
153     /**
154      * @param s the String to escape
155      * @return the String with \ before escaped chars
156      */
157     private static String escape(String s)
158     {
159         String out = "";
160         for (char c : s.toCharArray())
161         {
162             if (escape.indexOf(c) >= 0)
163                 out += "\\";
164             if (c == '"')
165                 out += "&quot;";
166             else
167                 out += c;
168         }
169         return out.trim();
170     }
171 
172     /**
173      * Determine calculated absolute output path (root of the executable or Jar file). In case of an Eclipse run, ../../ is
174      * added to the path to place the results in the root of the project, rather than in target/classes.<br>
175      * See https://weblogs.java.net/blog/kohsuke/archive/2007/04/how_to_convert.html and
176      * http://stackoverflow.com/questions/320542/how-to-get-the-path-of-a-running-jar-file and
177      * http://stackoverflow.com/questions/3153337/get-current-working-directory-in-java
178      * @throws FileNotFoundException in case file could not be found
179      */
180     private static void makeAbsolutePath() throws FileNotFoundException
181     {
182         URL mainURL = URLResource.getResource("/");
183         String path;
184         try
185         {
186             path = mainURL.toURI().getPath();
187         }
188         catch (URISyntaxException exception)
189         {
190             path = mainURL.getPath();
191         }
192         if (path.endsWith("/target/classes/"))
193         {
194             path = path.substring(0, path.length() - "/target/classes/".length());
195         }
196         path += generatedCodeRelativePath;
197         if (!new File(path).exists())
198         {
199             new File(path).mkdirs();
200         }
201         absoluteRootPath = path;
202         System.out.println("writing into: " + path);
203     }
204 }