EOS 2  1.1.0
Einfache Objektbasierte Sprache
LangXMLScanner.java
gehe zur Dokumentation dieser Datei
1 package de.lathanda.eos.config;
2 
3 import java.util.Iterator;
4 import java.util.LinkedList;
5 import java.util.Locale;
6 import java.util.ServiceLoader;
7 
8 import org.w3c.dom.Document;
9 import org.w3c.dom.Element;
10 import org.w3c.dom.Node;
11 import org.w3c.dom.NodeList;
12 
13 import de.lathanda.eos.base.extension.XMLProvider;
14 
15 public class LangXMLScanner {
16  private Language lang;
17  public LangXMLScanner(Language lang) {
18  this.lang = lang;
19  }
20  public void load() {
21  ServiceLoader<XMLProvider> sp = ServiceLoader.load(XMLProvider.class);
22  LinkedList<Document> docs = new LinkedList<>();
23  for(var xml : sp) {
24  for(Document d : xml.getXML()) {
25  docs.add(d);
26  }
27  }
28  while (!docs.isEmpty()) {
29  Document d = docs.pop();
30  try {
31  scan(d);
32  } catch (UnknownNodeException e) {
33  System.err.println(e.getLocalizedMessage());
34  e.printStackTrace();
35  }
36  }
37  }
38  public void scan(Document d) throws UnknownNodeException {
39  NodeList roots = d.getChildNodes();
40  for(int i = 0; i < roots.getLength(); i++) {
41  Node n = roots.item(i);
42  if (n instanceof Element) {
43  Element e = (Element)n;
44  switch(e.getTagName()) {
45  case "types":
46  scanTypes(e);
47  break;
48  case "lang":
49  scanLang(e);
50  break;
51  case "extension":
52  scanExtension(e);
53  break;
54  default:
55  throw new UnknownNodeException(n);
56  }
57  }
58  }
59  }
60  private void scanExtension(Element e) throws UnknownNodeException {
61  String extid = e.getAttribute("extends");
62  LanguageConfig lc = lang.getOrCreateLanguageConfig(extid);
63  scanLangBody(e, lc, false);
64  }
65  private void scanLang(Element e) throws UnknownNodeException {
66  String id = e.getAttribute("id");
67  LanguageConfig lc = lang.getOrCreateLanguageConfig(id);
68  scanLangBody(e, lc, true);
69  }
70  private void scanLangBody(Element n, LanguageConfig lc, boolean setParser) throws UnknownNodeException {
71  Locale locale = Locale.getDefault();
72  var body = n.getChildNodes();
73  Element text = null;
74  for(int i = 0; i < body.getLength(); i++) {
75  Node node = body.item(i);
76  if (node.getNodeType() == Node.ELEMENT_NODE) {
77  Element e = (Element)node;
78  switch (e.getTagName()) {
79  case "text":
80  if (text == null) {
81  text = e;
82  }
83  String country = e.getAttribute("lang");
84  if (locale.getLanguage().equals(new Locale(country).getLanguage())) {
85  text = e;
86  }
87  break;
88  default:
89  throw new UnknownNodeException(node);
90  }
91  }
92  }
93  if (text != null) {
94  if (setParser) {
95  String parser = text.getAttribute("parser");
96  lc.setParser(parser);
97  }
98  scanText(text, lc);
99  }
100  }
101  private void scanText(Element text, LanguageConfig lc) throws UnknownNodeException {
102  var body = text.getChildNodes();
103  for(int i = 0; i < body.getLength(); i++) {
104  Node node = body.item(i);
105  if (node.getNodeType() == Node.ELEMENT_NODE) {
106  Element e = (Element)node;
107  switch (e.getTagName()) {
108  case "label":
109  lc.setLabel(e.getTextContent().trim());
110  break;
111  case "tooltip":
112  lc.setTooltip(e.getTextContent().trim());
113  break;
114  case "description":
115  lc.setDescription(readHtmlContent(e));
116  break;
117  case "class":
118  scanClassT(e, lc);
119  break;
120  case "help":
121  scanHelp(e, lc);
122  break;
123  case "module":
124  scanModuleT(e, lc);
125  break;
126  case "system":
127  scanSystem(e, lc);
128  break;
129  case "menuitem":
130  lc.addMenuItem(e.getAttribute("id"), e.getAttribute("pid"), e.getAttribute("label"), e.getAttribute("action"), e.getTextContent().trim());
131  break;
132  case "templates":
133  scanTemplates(e, lc);
134  break;
135  default:
136  throw new UnknownNodeException(node);
137  }
138  }
139  }
140  }
141  private void scanTemplates(Element templates, LanguageConfig lc) throws UnknownNodeException {
142  var t = templates.getChildNodes();
143  for(int i = 0; i < t.getLength(); i++) {
144  Node node = t.item(i);
145  if (node.getNodeType() == Node.ELEMENT_NODE) {
146  Element e = (Element)node;
147  switch (e.getTagName()) {
148  case "template":
149  {
150  LangTemplate lt = new LangTemplate();
151  lt.id = e.getAttribute("id");
152  var temp = e.getChildNodes();
153  for(int j = 0; j < temp.getLength(); j++) {
154  Node node2 = temp.item(j);
155  if (node2.getNodeType() == Node.ELEMENT_NODE) {
156  Element ele = (Element)node2;
157  switch (ele.getTagName()) {
158  case "label":
159  lt.label = ele.getTextContent().trim();
160  break;
161  case "content":
162  readTemplateContent(ele, lt);
163  break;
164  default:
165  throw new UnknownNodeException(node);
166  }
167  }
168 
169  }
170  lc.addTemplate(lt);
171  break;
172  }
173  default:
174  throw new UnknownNodeException(node);
175  }
176  }
177  }
178  }
179  private void scanSystem(Element e, LanguageConfig lc) throws UnknownNodeException {
180  //Hard coded system variable names
181  //ReservedVariables Interface, used in Unit class for diagram display
182  //In diagrams system variables like loop count become visible, the values
183  //are used to exchange the hard coded ids with user readable translated names
184  var labels = e.getChildNodes();
185  for(int i = 0; i < labels.getLength(); i++) {
186  Node label = labels.item(i);
187  if (label.getNodeType() == Node.ELEMENT_NODE) {
188  Element lab = (Element)label;
189  switch (lab.getTagName()) {
190  case "label":
191  lc.registerName(lab.getAttribute("id"), lab.getTextContent().trim());
192  break;
193  default:
194  throw new UnknownNodeException(lab);
195  }
196  }
197  }
198  }
199 
200  private void scanModuleT(Element e, LanguageConfig lc) throws UnknownNodeException {
201  LangModule lm = lc.getOrCreateLangModule(e.getAttribute("id"));
202  lm.javaclass = e.getAttribute("class");
203  var functions = e.getChildNodes();
204  for(int i = 0; i < functions.getLength(); i++) {
205  Node function = functions.item(i);
206  if (function.getNodeType() == Node.ELEMENT_NODE) {
207  Element functionE = (Element)function;
208  switch (functionE.getTagName()) {
209  case "label":
210  lm.label = functionE.getTextContent().trim();
211  break;
212  case "tooltip":
213  lm.tooltip = readHtmlContent(functionE);
214  break;
215  case "description":
216  lm.description = readHtmlContent(functionE);
217  break;
218  case "function":
219  scanFunction(functionE, lm, lc);
220  break;
221  default:
222  throw new UnknownNodeException(function);
223  }
224  }
225  }
226  }
227  private void scanFunction(Element function, LangModule module, LanguageConfig lc) throws UnknownNodeException {
228  LangFunction lf = module.getOrCreateFunction(function.getAttribute("id"));
229  var children = function.getChildNodes();
230  var parameters = function.getElementsByTagName("parameter");
231  for(int i = lf.parameters.size(); i < parameters.getLength(); i++) {
232  lf.parameters.add(new LangParameter());
233  }
234  Iterator<LangParameter> ip = lf.parameters.iterator();
235  for(int i = 0; i < parameters.getLength(); i++) {
236  Node child = children.item(i);
237  if (child.getNodeType() == Node.ELEMENT_NODE) {
238  Element childE = (Element)child;
239  switch (childE.getTagName()) {
240  case "label":
241  lf.label = childE.getTextContent().trim();
242  case "tooltip":
243  lf.tooltip = readHtmlContent(childE);
244  break;
245  case "description":
246  lf.description = readHtmlContent(childE);
247  break;
248  case "parameter":
249  LangParameter lp = ip.next();
250  scanParameter(childE, lp);
251  break;
252  default:
253  throw new UnknownNodeException(function);
254  }
255  }
256  }
257  }
258  private void scanParameter(Element parameter, LangParameter lp) throws UnknownNodeException {
259  lp.name = parameter.getAttribute("name");
260  var children = parameter.getChildNodes();
261  for(int i = 0; i < children.getLength(); i++) {
262  Node child = children.item(i);
263  if (child.getNodeType() == Node.ELEMENT_NODE) {
264  Element childe = (Element)child;
265  switch (childe.getTagName()) {
266  case "tooltip":
267  lp.tooltip = readHtmlContent(childe);
268  break;
269  case "description":
270  lp.description = readHtmlContent(childe);
271  break;
272  default:
273  throw new UnknownNodeException(childe);
274  }
275  }
276  }
277  }
278  private void scanHelp(Element e, LanguageConfig lc) throws UnknownNodeException {
279  LangHelp lh = new LangHelp(e.getAttribute("id"));
280  lh.pid = e.getAttribute("parent");
281  lh.description = "";
282  lh.title = "";
283  var children = e.getChildNodes();
284  for(int i = 0; i < children.getLength(); i++) {
285  Node child = children.item(i);
286  if (child.getNodeType() == Node.ELEMENT_NODE) {
287  Element childe = (Element)child;
288  switch (childe.getTagName()) {
289  case "label":
290  lh.title = childe.getTextContent().trim();
291  break;
292  case "tooltip":
293  lh.tooltip = childe.getTextContent().trim();
294  break;
295  case "description":
296  lh.description = readHtmlContent(childe);
297  break;
298  case "example":
299  lh.examples.add(childe.getAttribute("file"));
300  break;
301  default:
302  throw new UnknownNodeException(childe);
303  }
304  }
305  }
306  lc.registerHelp(lh);
307  }
308  private void scanClassT(Element e, LanguageConfig lc) throws UnknownNodeException {
309  LangClass langc = lc.getOrCreateLangClass(e.getAttribute("id"));
310  langc.description = "";
311  langc.show = !e.getAttribute("show").equals("false"); //"" has to be true, therefore we accept any none false text as true
312  if (e.getAttribute("scan").isBlank()) {
313  langc.scan = new String[] {}; //empty scan attribute means existent, but auto completion invisible method, for example deprecation
314  //remark String.split on "" does return an Array of size 1 split on ",," will return an empty array.
315  //isn't java a beautiful and logical language?
316  } else {
317  langc.scan = e.getAttribute("scan").split(",");
318  for(int i = 0; i < langc.scan.length; i++) {
319  langc.scan[i] = langc.scan[i].trim();
320  }
321  }
322  var children = e.getChildNodes();
323  for(int i = 0; i < children.getLength(); i++) {
324  Node child = children.item(i);
325  if (child.getNodeType() == Node.ELEMENT_NODE) {
326  Element childe = (Element)child;
327  switch (childe.getTagName()) {
328  case "label":
329  langc.label = childe.getTextContent().trim();
330  break;
331  case "tooltip":
332  langc.tooltip = readHtmlContent(childe);
333  break;
334  case "description":
335  langc.description = readHtmlContent(childe);
336  break;
337  case "example":
338  langc.examples.add(childe.getAttribute("file"));
339  break;
340  case "property":
341  LangProperty lp = langc.getOrCreateProperty(childe.getAttribute("id"));
342  scanProperty(lp, childe);
343  break;
344  case "method":
345  LangMethod lm = langc.getOrCreateMethod(childe.getAttribute("id"));
346  scanMethod(lm, childe);
347  break;
348  default:
349  throw new UnknownNodeException(childe);
350  }
351  }
352  }
353  }
354  private void scanProperty(LangProperty lp, Element e) throws UnknownNodeException {
355  lp.scan = e.getAttribute("scan");
356  assert(!lp.scan.isEmpty());
357  var children = e.getChildNodes();
358  for(int i = 0; i < children.getLength(); i++) {
359  Node child = children.item(i);
360  if (child.getNodeType() == Node.ELEMENT_NODE) {
361  Element childe = (Element)child;
362  switch (childe.getTagName()) {
363  case "label":
364  lp.label = childe.getTextContent().trim();
365  break;
366  case "tooltip":
367  lp.tooltip = readHtmlContent(childe);
368  break;
369  case "description":
370  lp.description = readHtmlContent(childe);
371  break;
372  default:
373  throw new UnknownNodeException(childe);
374  }
375  }
376  }
377  }
378  private void scanMethod(LangMethod lm, Element e) throws UnknownNodeException {
379  lm.scan = e.getAttribute("scan");
380  assert(!lm.scan.isEmpty());
381  var parameters = e.getElementsByTagName("parameter");
382  for(int i= lm.parameters.size(); i < parameters.getLength(); i++) {
383  lm.parameters.add(new LangParameter());
384  }
385  Iterator<LangParameter> ip = lm.parameters.iterator();
386 
387  var children = e.getChildNodes();
388  for(int i = 0; i < children.getLength(); i++) {
389  Node child = children.item(i);
390  if (child.getNodeType() == Node.ELEMENT_NODE) {
391  Element childe = (Element)child;
392  switch (childe.getTagName()) {
393  case "label":
394  lm.label = childe.getTextContent().trim();
395  break;
396  case "tooltip":
397  lm.tooltip = readHtmlContent(childe);
398  break;
399  case "description":
400  lm.description = readHtmlContent(childe);
401  break;
402  case "parameter":
403  LangParameter lp = ip.next();
404  scanParameter(childe, lp);
405  break;
406  default:
407  throw new UnknownNodeException(childe);
408  }
409  }
410  }
411  }
412  private void scanTypes(Element e) throws UnknownNodeException {
413  //technical class file
414  var children = e.getChildNodes();
415  for(int i = 0; i < children.getLength(); i++) {
416  Node child = children.item(i);
417  if (child.getNodeType() == Node.ELEMENT_NODE) {
418  Element childe = (Element)child;
419  switch (childe.getTagName()) {
420  case "class":
421  scanClass(childe);
422  break;
423  case "module":
424  scanModule(childe);
425  break;
426  default:
427  throw new UnknownNodeException(childe);
428  }
429  }
430  }
431 
432  }
433 
434  private void scanModule(Element mod) throws UnknownNodeException {
435  String javaclass = mod.getAttribute("class");
436  String id = mod.getAttribute("id");
437  lang.registerModule(id, javaclass);
438  var children = mod.getChildNodes();
439  for(int i = 0; i < children.getLength(); i++) {
440  Node child = children.item(i);
441  if (child.getNodeType() == Node.ELEMENT_NODE) {
442  Element childe = (Element)child;
443  switch (childe.getTagName()) {
444  case "function":
445  String f_id = childe.getAttribute("id");
446  String f_javamethod = childe.getAttribute("name");
447  String f_return = childe.getAttribute("return");
448  LinkedList<String> f_parameters = new LinkedList<>();
449  var parameters = childe.getChildNodes();
450  for(int j = 0; j < parameters.getLength(); j++) {
451  Node parameter = parameters.item(j);
452  if (parameter.getNodeType() == Node.ELEMENT_NODE) {
453  Element parae = (Element)parameter;
454  switch (parae.getTagName()) {
455  case "parameter":
456  f_parameters.add(parae.getAttribute("type"));
457  break;
458  default:
459  throw new UnknownNodeException(childe);
460  }
461  }
462  }
463  lang.registerGlobalFunction(id, f_id, f_javamethod, f_parameters, f_return);
464  break;
465  default:
466  throw new UnknownNodeException(childe);
467  }
468  }
469  }
470 
471  }
472  private void scanClass(Element cls) throws UnknownNodeException {
473  String javaclass = cls.getAttribute("class");
474  String id = cls.getAttribute("id");
475  String pid = cls.getAttribute("super");
476  lang.registerClass(id, pid, javaclass);
477  var children = cls.getChildNodes();
478  for(int i = 0; i < children.getLength(); i++) {
479  Node child = children.item(i);
480  if (child.getNodeType() == Node.ELEMENT_NODE) {
481  Element childe = (Element)child;
482  switch (childe.getTagName()) {
483  case "property":
484  String p_id = childe.getAttribute("id");
485  String p_type = childe.getAttribute("type");
486  String getter = childe.getAttribute("getter");
487  String setter = childe.getAttribute("setter");
488  String view = childe.getAttribute("view");
489  if (view.isEmpty()) {
490  view = getter;
491  }
492  lang.registerProperty(id, p_id, p_type, getter, setter, view);
493  break;
494  case "method":
495  String m_id = childe.getAttribute("id");
496  String m_javamethod = childe.getAttribute("name");
497  String m_return = childe.getAttribute("return");
498  LinkedList<String> m_parameters = new LinkedList<>();
499  var parameters = childe.getChildNodes();
500  for(int j = 0; j < parameters.getLength(); j++) {
501  Node parameter = parameters.item(j);
502  if (parameter.getNodeType() == Node.ELEMENT_NODE) {
503  Element parae = (Element)parameter;
504  switch (parae.getTagName()) {
505  case "parameter":
506  m_parameters.add(parae.getAttribute("type"));
507  break;
508  default:
509  throw new UnknownNodeException(childe);
510  }
511  }
512  }
513  lang.registerMethod(id, m_id, m_javamethod, m_parameters, m_return);
514  break;
515  default:
516  throw new UnknownNodeException(childe);
517  }
518  }
519  }
520  }
521  private String readHtmlContent(Element e) {
522  StringBuilder text = new StringBuilder();
523  var children = e.getChildNodes();
524  for(int i = 0; i < children.getLength(); i++) {
525  Node child = children.item(i);
526  if (child.getNodeType() == Node.ELEMENT_NODE) {
527  Element childe = (Element)child;
528  switch (childe.getTagName()) {
529  case "indent":
530  text.append("&nbsp;&nbsp;&nbsp;&nbsp;");
531  break;
532  case "nbsp":
533  text.append("&nbsp;");
534  break;
535  default:
536  if (childe.getTextContent().isEmpty()) {
537  text.append("<"+childe.getTagName()+"/>");
538  } else {
539  text.append("<"+childe.getTagName()+">");
540  text.append(childe.getTextContent());
541  text.append("</"+childe.getTagName()+">");
542  }
543  }
544  } else {
545  text.append(child.getTextContent());
546  }
547  }
548  String html = text.toString();
549  html = html.replaceAll("\u00B1", "&plusmn;");
550  html = html.replaceAll("Ü", "&Uuml;");
551  html = html.replaceAll("ü", "&uuml;");
552  html = html.replaceAll("Ä", "&Auml;");
553  html = html.replaceAll("ä", "&auml;");
554  html = html.replaceAll("Ö", "&Ouml;");
555  html = html.replaceAll("ö", "&ouml;");
556  html = html.replaceAll("ß", "&szlig;");
557  return html;
558  }
559  private void readTemplateContent(Element e, LangTemplate lt) {
560  var children = e.getChildNodes();
561  boolean newline = true;
562  lt.start = -1;
563  lt.length = 0;
564  StringBuilder text = new StringBuilder();
565  for(int i = 0; i < children.getLength(); i++) {
566  Node child = children.item(i);
567  if (child.getNodeType() == Node.ELEMENT_NODE) {
568  Element childe = (Element)child;
569  switch (childe.getTagName()) {
570  case "indent":
571  text.append(" ");
572  newline = false;
573  break;
574  case "select":
575  lt.start = text.length();
576  text.append(childe.getTextContent());
577  lt.length = text.length() - lt.start;
578  newline = false;
579  break;
580  case "br":
581  text.append("\n");
582  newline = true;
583  break;
584  case "nbsp":
585  text.append(" ");
586  newline = false;
587  }
588  } else {
589  if (newline) {
590  text.append(getPackedContent(child).replaceAll("^\\s+",""));
591  } else {
592  text.append(getPackedContent(child));
593  }
594  }
595  }
596  lt.template = text.toString().replaceAll("\\s+$","");
597  }
598  private static String getPackedContent(Node element) {
599  if (element != null) {
600  String text = element.getTextContent();
601  if (text != null) {
602  return text.replaceAll("\\s+", " ");
603  }
604  }
605  return "";
606  }
607 }
Impressum