FullSyntaxBuilder.java 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651
  1. /* FullSyntaxBuilder.java --
  2. Copyright (C) 2006 Free Software Foundation, Inc.
  3. This file is part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. 02110-1301 USA.
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version. */
  31. package gnu.xml.validation.relaxng;
  32. import java.io.InputStream;
  33. import java.io.IOException;
  34. import java.io.UnsupportedEncodingException;
  35. import java.net.URL;
  36. import java.net.URLEncoder;
  37. import java.util.Collections;
  38. import java.util.HashMap;
  39. import java.util.HashSet;
  40. import java.util.Iterator;
  41. import java.util.LinkedList;
  42. import java.util.List;
  43. import java.util.Map;
  44. import java.util.Set;
  45. import javax.xml.XMLConstants;
  46. import javax.xml.parsers.DocumentBuilder;
  47. import javax.xml.parsers.DocumentBuilderFactory;
  48. import javax.xml.parsers.ParserConfigurationException;
  49. import org.relaxng.datatype.DatatypeException;
  50. import org.relaxng.datatype.DatatypeLibrary;
  51. import org.relaxng.datatype.helpers.DatatypeLibraryLoader;
  52. import org.w3c.dom.Document;
  53. import org.w3c.dom.Element;
  54. import org.w3c.dom.NamedNodeMap;
  55. import org.w3c.dom.Node;
  56. import org.xml.sax.SAXException;
  57. import gnu.xml.stream.XMLParser;
  58. /**
  59. * Parses a RELAX NG XML DOM tree, constructing a compiled internal
  60. * representation.
  61. *
  62. * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
  63. */
  64. class FullSyntaxBuilder
  65. {
  66. /**
  67. * Complete vocabulary (elements and attributes) of the full syntax.
  68. */
  69. static final Map VOCABULARY = new HashMap();
  70. static final Set STRIPPED_ATTRIBUTES = new HashSet();
  71. static final Set PATTERN_ELEMENTS = new HashSet();
  72. static
  73. {
  74. Set elementAttrs = Collections.singleton("name");
  75. Set dataAttrs = new HashSet();
  76. dataAttrs.add("type");
  77. dataAttrs.add("datatypeLibrary");
  78. Set valueAttrs = new HashSet();
  79. valueAttrs.add("type");
  80. valueAttrs.add("datatypeLibrary");
  81. valueAttrs.add("ns");
  82. Set externalAttrs = Collections.singleton("href");
  83. Set startAttrs = Collections.singleton("combine");
  84. Set defineAttrs = new HashSet();
  85. defineAttrs.add("name");
  86. defineAttrs.add("combine");
  87. Set nsAttrs = Collections.singleton("ns");
  88. VOCABULARY.put("element", elementAttrs);
  89. VOCABULARY.put("attribute", elementAttrs);
  90. VOCABULARY.put("group", Collections.EMPTY_SET);
  91. VOCABULARY.put("interleave", Collections.EMPTY_SET);
  92. VOCABULARY.put("choice", Collections.EMPTY_SET);
  93. VOCABULARY.put("optional", Collections.EMPTY_SET);
  94. VOCABULARY.put("zeroOrMore", Collections.EMPTY_SET);
  95. VOCABULARY.put("oneOrMore", Collections.EMPTY_SET);
  96. VOCABULARY.put("list", Collections.EMPTY_SET);
  97. VOCABULARY.put("mixed", Collections.EMPTY_SET);
  98. VOCABULARY.put("ref", elementAttrs);
  99. VOCABULARY.put("parentRef", elementAttrs);
  100. VOCABULARY.put("empty", Collections.EMPTY_SET);
  101. VOCABULARY.put("text", Collections.EMPTY_SET);
  102. VOCABULARY.put("value", valueAttrs);
  103. VOCABULARY.put("data", dataAttrs);
  104. VOCABULARY.put("notAllowed", Collections.EMPTY_SET);
  105. VOCABULARY.put("externalRef", externalAttrs);
  106. VOCABULARY.put("grammar", Collections.EMPTY_SET);
  107. VOCABULARY.put("param", elementAttrs);
  108. VOCABULARY.put("except", Collections.EMPTY_SET);
  109. VOCABULARY.put("div", Collections.EMPTY_SET);
  110. VOCABULARY.put("include", externalAttrs);
  111. VOCABULARY.put("start", startAttrs);
  112. VOCABULARY.put("define", defineAttrs);
  113. VOCABULARY.put("name", nsAttrs);
  114. VOCABULARY.put("anyName", Collections.EMPTY_SET);
  115. VOCABULARY.put("nsName", nsAttrs);
  116. STRIPPED_ATTRIBUTES.add("name");
  117. STRIPPED_ATTRIBUTES.add("type");
  118. STRIPPED_ATTRIBUTES.add("combine");
  119. PATTERN_ELEMENTS.add("element");
  120. PATTERN_ELEMENTS.add("attribute");
  121. PATTERN_ELEMENTS.add("group");
  122. PATTERN_ELEMENTS.add("interleave");
  123. PATTERN_ELEMENTS.add("choice");
  124. PATTERN_ELEMENTS.add("optional");
  125. PATTERN_ELEMENTS.add("zeroOrMore");
  126. PATTERN_ELEMENTS.add("oneOrMore");
  127. PATTERN_ELEMENTS.add("list");
  128. PATTERN_ELEMENTS.add("mixed");
  129. PATTERN_ELEMENTS.add("ref");
  130. PATTERN_ELEMENTS.add("parentRef");
  131. PATTERN_ELEMENTS.add("empty");
  132. PATTERN_ELEMENTS.add("text");
  133. PATTERN_ELEMENTS.add("value");
  134. PATTERN_ELEMENTS.add("data");
  135. PATTERN_ELEMENTS.add("notAllowed");
  136. PATTERN_ELEMENTS.add("externalRef");
  137. PATTERN_ELEMENTS.add("grammar");
  138. }
  139. private Set urls; // recursion checking
  140. private int refCount; // creation of ref names
  141. private Map datatypeLibraries;
  142. /**
  143. * Parse the specified document into a grammar.
  144. */
  145. synchronized Grammar parse(Document doc)
  146. throws IOException
  147. {
  148. urls = new HashSet();
  149. refCount = 1;
  150. doc.normalizeDocument(); // Normalize XML document
  151. transform(doc); // Apply transformation rules to provide simple syntax
  152. // 4.18. grammar element
  153. Element p = doc.getDocumentElement();
  154. Element grammar =
  155. doc.createElementNS(XMLConstants.RELAXNG_NS_URI, "grammar");
  156. Element start =
  157. doc.createElementNS(XMLConstants.RELAXNG_NS_URI, "start");
  158. doc.removeChild(p);
  159. doc.appendChild(grammar);
  160. grammar.appendChild(start);
  161. start.appendChild(p);
  162. transformGrammar(grammar, p);
  163. Element define = getNextSiblingElement(start);
  164. while (define != null)
  165. {
  166. Element next = getNextSiblingElement(define);
  167. String name = define.getAttribute("new-name");
  168. if (name != null)
  169. {
  170. define.setAttribute("name", name);
  171. define.removeAttribute("new-name");
  172. }
  173. else
  174. grammar.removeChild(define); // unreferenced
  175. define = next;
  176. }
  177. // 4.19. define and ref elements
  178. Set allDefines = new HashSet(), reachableDefines = new HashSet();
  179. getDefines(allDefines, grammar, grammar, false);
  180. getDefines(reachableDefines, grammar, start, true);
  181. allDefines.removeAll(reachableDefines);
  182. for (Iterator i = allDefines.iterator(); i.hasNext(); )
  183. {
  184. // remove unreachable defines
  185. Element d = (Element) i.next();
  186. Node parent = d.getParentNode();
  187. parent.removeChild(d);
  188. }
  189. // replace all elements that are not children of defines by refs to new
  190. // defines
  191. Set elements = new HashSet();
  192. getElements(elements, grammar, grammar);
  193. for (Iterator i = elements.iterator(); i.hasNext(); )
  194. {
  195. Element element = (Element) i.next();
  196. Node parent = element.getParentNode();
  197. if (!reachableDefines.contains(parent))
  198. {
  199. define =
  200. doc.createElementNS(XMLConstants.RELAXNG_NS_URI, "define");
  201. Element ref =
  202. doc.createElementNS(XMLConstants.RELAXNG_NS_URI, "ref");
  203. String name = createRefName();
  204. define.setAttribute("name", name);
  205. ref.setAttribute("name", name);
  206. parent.insertBefore(ref, element);
  207. define.appendChild(element);
  208. grammar.appendChild(define);
  209. reachableDefines.add(define);
  210. }
  211. }
  212. // Get defines that don't have element children
  213. for (Iterator i = reachableDefines.iterator(); i.hasNext(); )
  214. {
  215. Element d = (Element) i.next();
  216. Element child = getFirstChildElement(d);
  217. if (child != null && "element".equals(child.getLocalName()))
  218. i.remove();
  219. }
  220. // Expand refs that refer to these defines
  221. expandRefs(reachableDefines, grammar);
  222. // Remove any defines that don't have element children
  223. for (Iterator i = reachableDefines.iterator(); i.hasNext(); )
  224. {
  225. Element d = (Element) i.next();
  226. Node parent = d.getParentNode();
  227. parent.removeChild(d);
  228. }
  229. transform2(p); // Apply second stage transformation rules
  230. Grammar ret = parseGrammar(grammar);
  231. datatypeLibraries = null; // free datatype libraries cache
  232. return ret;
  233. }
  234. private void getDefines(Set defines, Element grammar, Element node,
  235. boolean followRefs)
  236. {
  237. String elementName = node.getLocalName();
  238. if ("define".equals(elementName))
  239. defines.add(node);
  240. else if ("ref".equals(elementName) && followRefs)
  241. {
  242. String rname = node.getAttribute("name");
  243. Element define = getFirstChildElement(grammar);
  244. define = getNextSiblingElement(define);
  245. while (define != null)
  246. {
  247. String dname = define.getAttribute("name");
  248. if (rname.equals(dname))
  249. {
  250. getDefines(defines, grammar, node, followRefs);
  251. break;
  252. }
  253. define = getNextSiblingElement(define);
  254. }
  255. }
  256. for (Element child = getFirstChildElement(node); child != null;
  257. child = getNextSiblingElement(child))
  258. getDefines(defines, grammar, child, followRefs);
  259. }
  260. private void getElements(Set elements, Element grammar, Element node)
  261. {
  262. String elementName = node.getLocalName();
  263. if ("element".equals(elementName))
  264. elements.add(node);
  265. for (Element child = getFirstChildElement(node); child != null;
  266. child = getNextSiblingElement(child))
  267. getElements(elements, grammar, child);
  268. }
  269. private void expandRefs(Set defines, Element node)
  270. throws GrammarException
  271. {
  272. String elementName = node.getLocalName();
  273. if ("ref".equals(elementName))
  274. {
  275. String rname = node.getAttribute("name");
  276. for (Iterator i = defines.iterator(); i.hasNext(); )
  277. {
  278. Element define = (Element) i.next();
  279. String dname = define.getAttribute("name");
  280. if (rname.equals(dname))
  281. {
  282. Element child = getFirstChildElement(define);
  283. forbidRefs(child, rname);
  284. Element refChild = (Element) child.cloneNode(true);
  285. Node parent = node.getParentNode();
  286. parent.insertBefore(refChild, node);
  287. parent.removeChild(node);
  288. node = refChild;
  289. break;
  290. }
  291. }
  292. }
  293. for (Element child = getFirstChildElement(node); child != null;
  294. child = getNextSiblingElement(child))
  295. expandRefs(defines, child);
  296. }
  297. private void forbidRefs(Element node, String name)
  298. throws GrammarException
  299. {
  300. String elementName = node.getLocalName();
  301. if ("ref".equals(elementName))
  302. {
  303. String rname = node.getAttribute("name");
  304. if (name.equals(rname))
  305. throw new GrammarException("cannot expand ref with name '" + name +
  306. "' due to circularity");
  307. }
  308. for (Element child = getFirstChildElement(node); child != null;
  309. child = getNextSiblingElement(child))
  310. forbidRefs(child, name);
  311. }
  312. private void transform(Node node)
  313. throws IOException
  314. {
  315. Node parent = node.getParentNode();
  316. switch (node.getNodeType())
  317. {
  318. case Node.ELEMENT_NODE:
  319. // 4.1 Annotations
  320. String elementNs = node.getNamespaceURI();
  321. String elementName = node.getLocalName();
  322. if (!XMLConstants.RELAXNG_NS_URI.equals(elementNs) ||
  323. !VOCABULARY.containsKey(elementName))
  324. parent.removeChild(node);
  325. else
  326. {
  327. Set allowedAttrs = (Set) VOCABULARY.get(elementName);
  328. NamedNodeMap attrs = node.getAttributes();
  329. int len = attrs.getLength();
  330. for (int i = len - 1; i >= 0; i--)
  331. {
  332. Node attr = attrs.item(i);
  333. String attrNs = attr.getNamespaceURI();
  334. String attrName = attr.getLocalName();
  335. if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(attrNs))
  336. continue; // ignore namespace nodes
  337. if (!(XMLConstants.RELAXNG_NS_URI.equals(attrNs) ||
  338. attrNs == null) ||
  339. !allowedAttrs.contains(attrName))
  340. attrs.removeNamedItemNS(attrNs, attrName);
  341. else
  342. {
  343. // 4.2 Whitespace
  344. if (STRIPPED_ATTRIBUTES.contains(attrName))
  345. attr.setNodeValue(attr.getNodeValue().trim());
  346. // 4.3 datatypeLibrary attribute
  347. else if ("datatypeLibrary".equals(attrName))
  348. {
  349. String dl = attr.getNodeValue();
  350. attr.setNodeValue(escapeURL(dl));
  351. }
  352. // 4.5. href attribute
  353. else if ("href".equals(attrName))
  354. {
  355. String href = attr.getNodeValue();
  356. href = XMLParser.absolutize(node.getBaseURI(),
  357. escapeURL(href));
  358. attr.setNodeValue(href);
  359. }
  360. }
  361. }
  362. // 4.3 datatypeLibrary attribute
  363. if ("data".equals(elementName) || "value".equals(elementName))
  364. {
  365. Element element = (Element) node;
  366. String dl = element.getAttribute("datatypeLibrary");
  367. if (dl == null)
  368. {
  369. Node p = parent;
  370. while (dl == null && p != null &&
  371. p.getNodeType() == Node.ELEMENT_NODE)
  372. {
  373. dl = ((Element) p)
  374. .getAttribute("datatypeLibrary");
  375. p = p.getParentNode();
  376. }
  377. if (dl == null)
  378. dl = "";
  379. element.setAttribute("datatypeLibrary", dl);
  380. }
  381. // 4.4. type attribute of value element
  382. if ("value".equals(elementName))
  383. {
  384. String type = element.getAttribute("type");
  385. if (type == null)
  386. {
  387. element.setAttribute("type", "token");
  388. element.setAttribute("datatypeLibrary", "");
  389. }
  390. }
  391. // 4.16. Constraints
  392. // TODO validate type
  393. }
  394. // 4.6. externalRef element
  395. else if ("externalRef".equals(elementName))
  396. {
  397. Element externalRef = (Element) node;
  398. String href = externalRef.getAttribute("href");
  399. // check for recursion
  400. if (urls.contains(href))
  401. throw new GrammarException("recursive href");
  402. urls.add(href);
  403. Element element = resolve(href);
  404. String eNs = element.getNamespaceURI();
  405. String eName = element.getLocalName();
  406. if (!(XMLConstants.RELAXNG_NS_URI.equals(eNs) ||
  407. eNs == null) ||
  408. !PATTERN_ELEMENTS.contains(eName))
  409. throw new GrammarException("externally referenced element " +
  410. "is not a pattern");
  411. transform(element);
  412. urls.remove(href);
  413. String ns = element.getAttribute("ns");
  414. if (ns != null)
  415. element.setAttribute("ns",
  416. externalRef.getAttribute("ns"));
  417. element = (Element) externalRef.getOwnerDocument()
  418. .importNode(element, true);
  419. parent.replaceChild(element, externalRef);
  420. return;
  421. }
  422. // 4.7 include element
  423. else if ("include".equals(elementName))
  424. {
  425. Element include = (Element) node;
  426. String href = include.getAttribute("href");
  427. // check for recursion
  428. if (urls.contains(href))
  429. throw new GrammarException("recursive href");
  430. urls.add(href);
  431. Element element = resolve(href);
  432. String eNs = element.getNamespaceURI();
  433. String eName = element.getLocalName();
  434. if (!(XMLConstants.RELAXNG_NS_URI.equals(eNs) ||
  435. eNs == null) ||
  436. !"grammar".equals(eName))
  437. throw new GrammarException("included element is not " +
  438. "a grammar");
  439. transform(element);
  440. urls.remove(href);
  441. // handle components
  442. List includeComponents = getComponents(include);
  443. List grammarComponents = getComponents(element);
  444. for (Iterator i = includeComponents.iterator(); i.hasNext(); )
  445. {
  446. Element comp = (Element) i.next();
  447. String compName = comp.getLocalName();
  448. if ("start".equals(compName))
  449. {
  450. boolean found = false;
  451. for (Iterator j = grammarComponents.iterator();
  452. j.hasNext(); )
  453. {
  454. Element c2 = (Element) j.next();
  455. if ("start".equals(c2.getLocalName()))
  456. {
  457. c2.getParentNode().removeChild(c2);
  458. found = true;
  459. }
  460. }
  461. if (!found)
  462. throw new GrammarException("no start component in " +
  463. "included grammar");
  464. }
  465. else if ("define".equals(compName))
  466. {
  467. String name = comp.getAttribute("name");
  468. boolean found = false;
  469. for (Iterator j = grammarComponents.iterator();
  470. j.hasNext(); )
  471. {
  472. Element c2 = (Element) j.next();
  473. if ("define".equals(c2.getLocalName()) &&
  474. name.equals(c2.getAttribute("name")))
  475. {
  476. c2.getParentNode().removeChild(c2);
  477. found = true;
  478. }
  479. }
  480. if (!found)
  481. throw new GrammarException("no define component " +
  482. "with name '" + name +
  483. "' in included grammar");
  484. }
  485. }
  486. // transform to div element
  487. Document doc = include.getOwnerDocument();
  488. Element includeDiv =
  489. doc.createElementNS(XMLConstants.RELAXNG_NS_URI, "div");
  490. Element grammarDiv =
  491. doc.createElementNS(XMLConstants.RELAXNG_NS_URI, "div");
  492. // XXX copy include non-href attributes (none defined?)
  493. element = (Element) doc.importNode(element, true);
  494. Node ctx = element.getFirstChild();
  495. while (ctx != null)
  496. {
  497. Node next = ctx.getNextSibling();
  498. grammarDiv.appendChild(ctx);
  499. ctx = next;
  500. }
  501. includeDiv.appendChild(grammarDiv);
  502. ctx = include.getFirstChild();
  503. while (ctx != null)
  504. {
  505. Node next = ctx.getNextSibling();
  506. includeDiv.appendChild(ctx);
  507. ctx = next;
  508. }
  509. parent.replaceChild(includeDiv, include);
  510. transform(includeDiv);
  511. return;
  512. }
  513. // 4.8. name attribute of element and attribute elements
  514. else if ("attribute".equals(elementName) ||
  515. "element".equals(elementName))
  516. {
  517. Element element = (Element) node;
  518. String name = element.getAttribute("name");
  519. if (name != null)
  520. {
  521. Document doc = element.getOwnerDocument();
  522. Element n =
  523. doc.createElementNS(XMLConstants.RELAXNG_NS_URI, "name");
  524. n.appendChild(doc.createTextNode(name));
  525. Node first = element.getFirstChild();
  526. if (first != null)
  527. element.insertBefore(n, first);
  528. else
  529. element.appendChild(n);
  530. if ("attribute".equals(elementName))
  531. {
  532. String ns = element.getAttribute("ns");
  533. if (ns != null)
  534. {
  535. n.setAttribute("ns", ns);
  536. element.removeAttribute("ns");
  537. }
  538. }
  539. element.removeAttribute("name");
  540. }
  541. // 4.12. Number of child elements
  542. if ("attribute".equals(elementName))
  543. {
  544. if (getComponents(node).size() == 1)
  545. {
  546. Document doc = node.getOwnerDocument();
  547. Element text =
  548. doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
  549. "text");
  550. node.appendChild(text);
  551. }
  552. }
  553. else // element
  554. {
  555. if (node.getChildNodes().getLength() > 2)
  556. {
  557. // transform to 2 child elements
  558. Document doc = node.getOwnerDocument();
  559. Element child =
  560. doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
  561. "group");
  562. Node ctx = getFirstChildElement(node);
  563. ctx = getNextSiblingElement(ctx); // skip 1
  564. while (ctx != null)
  565. {
  566. Node next = getNextSiblingElement(ctx);
  567. child.appendChild(ctx);
  568. ctx = next;
  569. }
  570. node.appendChild(child);
  571. }
  572. }
  573. }
  574. // 4.11. div element
  575. else if ("div".equals(elementName))
  576. {
  577. Node ctx = node.getFirstChild();
  578. while (ctx != null)
  579. {
  580. Node next = ctx.getNextSibling();
  581. parent.insertBefore(ctx, node);
  582. transform(ctx);
  583. ctx = next;
  584. }
  585. parent.removeChild(node);
  586. return;
  587. }
  588. else if ("mixed".equals(elementName))
  589. {
  590. // 4.12. Number of child elements
  591. transformToOneChildElement(node, "group");
  592. // 4.13. mixed element
  593. Document doc = node.getOwnerDocument();
  594. Node interleave =
  595. doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
  596. "interleave");
  597. Node ctx = node.getFirstChild();
  598. while (ctx != null)
  599. {
  600. Node next = ctx.getNextSibling();
  601. interleave.appendChild(ctx);
  602. ctx = next;
  603. }
  604. Node text =
  605. doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
  606. "text");
  607. interleave.appendChild(text);
  608. parent.insertBefore(interleave, node);
  609. parent.removeChild(node);
  610. node = interleave;
  611. }
  612. else if ("optional".equals(elementName))
  613. {
  614. // 4.12. Number of child elements
  615. transformToOneChildElement(node, "group");
  616. // 4.14. optional element
  617. Document doc = node.getOwnerDocument();
  618. Node choice =
  619. doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
  620. "choice");
  621. Node ctx = node.getFirstChild();
  622. while (ctx != null)
  623. {
  624. Node next = ctx.getNextSibling();
  625. choice.appendChild(ctx);
  626. ctx = next;
  627. }
  628. Node empty =
  629. doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
  630. "empty");
  631. choice.appendChild(empty);
  632. parent.insertBefore(choice, node);
  633. parent.removeChild(node);
  634. node = choice;
  635. }
  636. else if ("zeroOrMore".equals(elementName))
  637. {
  638. // 4.12. Number of child elements
  639. transformToOneChildElement(node, "group");
  640. // 4.15. zeroOrMore element
  641. Document doc = node.getOwnerDocument();
  642. Node choice =
  643. doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
  644. "choice");
  645. Node oneOrMore =
  646. doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
  647. "oneOrMore");
  648. Node ctx = node.getFirstChild();
  649. while (ctx != null)
  650. {
  651. Node next = ctx.getNextSibling();
  652. oneOrMore.appendChild(ctx);
  653. ctx = next;
  654. }
  655. Node empty =
  656. doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
  657. "empty");
  658. choice.appendChild(oneOrMore);
  659. choice.appendChild(empty);
  660. parent.insertBefore(choice, node);
  661. parent.removeChild(node);
  662. node = choice;
  663. }
  664. else if ("list".equals(elementName) ||
  665. "oneOrMore".equals(elementName) ||
  666. "define".equals(elementName))
  667. {
  668. // 4.12. Number of child elements
  669. transformToOneChildElement(node, "group");
  670. }
  671. else if ("except".equals(elementName))
  672. {
  673. // 4.12. Number of child elements
  674. transformToOneChildElement(node, "choice");
  675. // 4.16. Constraints
  676. String parentName = parent.getLocalName();
  677. if ("anyName".equals(parentName))
  678. forbidDescendants(node, Collections.singleton("anyName"));
  679. else if ("nsName".equals(parentName))
  680. {
  681. Set names = new HashSet();
  682. names.add("nsName");
  683. names.add("anyName");
  684. forbidDescendants(node, names);
  685. }
  686. }
  687. else if ("choice".equals(elementName) ||
  688. "group".equals(elementName) ||
  689. "interleave".equals(elementName))
  690. {
  691. // 4.12. Number of child elements
  692. Node ctx = getFirstChildElement(node);
  693. Node next = getNextSiblingElement(ctx);
  694. if (next == null)
  695. {
  696. // replace
  697. parent.insertBefore(ctx, node);
  698. parent.removeChild(node);
  699. transform(ctx);
  700. return;
  701. }
  702. else
  703. {
  704. // transform to 2 child elements
  705. Node next2 = getNextSiblingElement(next);
  706. if (next2 != null)
  707. {
  708. Document doc = node.getOwnerDocument();
  709. Node child =
  710. doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
  711. elementName);
  712. child.appendChild(ctx);
  713. child.appendChild(next);
  714. node.insertBefore(next2, child);
  715. transform(node); // recurse
  716. }
  717. }
  718. }
  719. // 4.17. combine attribute
  720. else if ("grammar".equals(elementName))
  721. {
  722. String combine = null;
  723. List nodes = new LinkedList();
  724. Node ctx = node.getFirstChild();
  725. while (ctx != null)
  726. {
  727. Node next = ctx.getNextSibling();
  728. if ("start".equals(ctx.getLocalName()))
  729. {
  730. String c = ((Element) ctx).getAttribute("combine");
  731. if (combine != null && !combine.equals(c))
  732. throw new GrammarException("multiple start elements "+
  733. "but no combine attribute");
  734. combine = c;
  735. nodes.add(ctx);
  736. }
  737. ctx = next;
  738. }
  739. if (!nodes.isEmpty())
  740. combineNodes(node, combine, "start", nodes);
  741. // defines
  742. Map defines = new HashMap();
  743. Map defineCombines = new HashMap();
  744. ctx = node.getFirstChild();
  745. while (ctx != null)
  746. {
  747. Node next = ctx.getNextSibling();
  748. if ("define".equals(ctx.getLocalName()))
  749. {
  750. String name = ((Element) ctx).getAttribute("name");
  751. combine = (String) defineCombines.get(name);
  752. String c = ((Element) ctx).getAttribute("combine");
  753. if (combine != null && !combine.equals(c))
  754. throw new GrammarException("multiple define " +
  755. "elements with name '"+
  756. name + "' but no " +
  757. "combine attribute");
  758. defineCombines.put(name, c);
  759. nodes = (List) defines.get(name);
  760. if (nodes == null)
  761. {
  762. nodes = new LinkedList();
  763. defines.put(name, nodes);
  764. }
  765. nodes.add(ctx);
  766. }
  767. ctx = next;
  768. }
  769. for (Iterator i = defines.keySet().iterator(); i.hasNext(); )
  770. {
  771. String name = (String) i.next();
  772. combine = (String) defineCombines.get(name);
  773. nodes = (List) defines.get(name);
  774. if (!nodes.isEmpty())
  775. combineNodes(node, combine, "define", nodes);
  776. }
  777. }
  778. // 4.9. ns attribute
  779. if ("name".equals(elementName) ||
  780. "nsName".equals(elementName) ||
  781. "value".equals(elementName))
  782. {
  783. Element element = (Element) node;
  784. String ns = element.getAttribute("ns");
  785. if (ns == null)
  786. {
  787. Node ctx = parent;
  788. while (ns == null && ctx != null &&
  789. ctx.getNodeType() == Node.ELEMENT_NODE)
  790. {
  791. ns = ((Element) ctx).getAttribute("ns");
  792. ctx = ctx.getParentNode();
  793. }
  794. element.setAttribute("ns", (ns == null) ? "" : ns);
  795. }
  796. if ("name".equals(elementName))
  797. {
  798. // 4.10. QNames
  799. String name = element.getTextContent();
  800. int ci = name.indexOf(':');
  801. if (ci != -1)
  802. {
  803. String prefix = name.substring(0, ci);
  804. element.setTextContent(name.substring(ci + 1));
  805. ns = element.lookupNamespaceURI(prefix);
  806. element.setAttribute("ns", (ns == null) ? "" : ns);
  807. }
  808. // 4.16. Constraints
  809. if (isDescendantOfFirstChildOfAttribute(element) &&
  810. "".equals(element.getAttribute("ns")) &&
  811. "xmlns".equals(element.getTextContent()))
  812. throw new GrammarException("name cannot be xmlns");
  813. }
  814. else if ("nsName".equals(elementName))
  815. {
  816. // 4.16. Constraints
  817. if (isDescendantOfFirstChildOfAttribute(element) &&
  818. "http://www.w3.org/2000/xmlns"
  819. .equals(element.getAttribute("ns")))
  820. throw new GrammarException("nsName cannot be XMLNS URI");
  821. }
  822. }
  823. }
  824. break;
  825. case Node.TEXT_NODE:
  826. case Node.CDATA_SECTION_NODE:
  827. // 4.2 Whitespace
  828. String parentName = parent.getLocalName();
  829. if ("name".equals(parentName))
  830. node.setNodeValue(node.getNodeValue().trim());
  831. if (!"param".equals(parentName) &&
  832. !"value".equals(parentName) &&
  833. isWhitespace(node.getNodeValue()))
  834. parent.removeChild(node);
  835. break;
  836. case Node.DOCUMENT_NODE:
  837. break;
  838. default:
  839. parent.removeChild(node);
  840. }
  841. // Transform children
  842. Node ctx = node.getFirstChild();
  843. while (ctx != null)
  844. {
  845. Node next = ctx.getNextSibling();
  846. transform(ctx);
  847. ctx = next;
  848. }
  849. }
  850. /**
  851. * Transforms the schema to place all defines under the top-level grammar
  852. * element and replace all other grammar elements by their start child.
  853. */
  854. private void transformGrammar(Node grammar, Node node)
  855. throws GrammarException
  856. {
  857. if (node.getNodeType() == Node.ELEMENT_NODE)
  858. {
  859. String elementName = node.getLocalName();
  860. if ("grammar".equals(elementName))
  861. {
  862. handleRefs(grammar, node, node);
  863. Node start = null;
  864. Node ctx = node.getFirstChild();
  865. while (ctx != null)
  866. {
  867. Node next = ctx.getNextSibling();
  868. String childName = ctx.getLocalName();
  869. if ("define".equals(childName))
  870. grammar.appendChild(ctx);
  871. else if ("start".equals(childName))
  872. start = ctx;
  873. ctx = next;
  874. }
  875. if (start == null)
  876. throw new GrammarException("no start element for grammar");
  877. Node p = getFirstChildElement(start);
  878. Node parent = node.getParentNode();
  879. parent.insertBefore(p, node);
  880. parent.removeChild(node);
  881. node = p;
  882. }
  883. Node ctx = node.getFirstChild();
  884. while (ctx != null)
  885. {
  886. Node next = ctx.getNextSibling();
  887. transformGrammar(grammar, ctx);
  888. ctx = next;
  889. }
  890. }
  891. }
  892. /**
  893. * Checks that all references in the specified grammar match a define in
  894. * the grammar.
  895. */
  896. private void handleRefs(Node grammar1, Node grammar2, Node node)
  897. throws GrammarException
  898. {
  899. if (node.getNodeType() == Node.ELEMENT_NODE)
  900. {
  901. String elementName = node.getLocalName();
  902. if ("ref".equals(elementName) || "parentRef".equals(elementName))
  903. {
  904. Node grammar = grammar2;
  905. if ("parentRef".equals(elementName))
  906. grammar = grammar1;
  907. String name = ((Element) node).getAttribute("name");
  908. if (name != null)
  909. throw new GrammarException("no name attribute on " +
  910. elementName);
  911. Node define = null;
  912. for (Node ctx = grammar.getFirstChild();
  913. define == null && ctx != null;
  914. ctx = ctx.getNextSibling())
  915. {
  916. if ("define".equals(ctx.getLocalName()))
  917. {
  918. String dname = ((Element) ctx).getAttribute("name");
  919. if (name.equals(dname))
  920. define = ctx;
  921. }
  922. }
  923. if (define == null)
  924. throw new GrammarException("no define for '" + name + "'");
  925. name = ((Element) define).getAttribute("new-name");
  926. if (name == null)
  927. {
  928. name = createRefName();
  929. ((Element) define).setAttribute("new-name", name);
  930. }
  931. if ("parentRef".equals(elementName))
  932. {
  933. Document doc = node.getOwnerDocument();
  934. Node ref = doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
  935. "ref");
  936. Node ctx = node.getFirstChild();
  937. while (ctx != null)
  938. {
  939. Node next = ctx.getNextSibling();
  940. ref.appendChild(ctx);
  941. ctx = next;
  942. }
  943. Node parent = node.getParentNode();
  944. parent.insertBefore(ref, node);
  945. parent.removeChild(node);
  946. node = ref;
  947. }
  948. ((Element) node).setAttribute("name", name);
  949. }
  950. else if ("grammar".equals(elementName))
  951. {
  952. grammar1 = grammar2;
  953. grammar2 = node;
  954. }
  955. Node ctx = node.getFirstChild();
  956. while (ctx != null)
  957. {
  958. Node next = ctx.getNextSibling();
  959. handleRefs(grammar1, grammar2, ctx);
  960. ctx = next;
  961. }
  962. }
  963. }
  964. private String createRefName()
  965. {
  966. return "ref" + Integer.toString(refCount++);
  967. }
  968. private void transform2(Node node)
  969. throws GrammarException
  970. {
  971. Node parent = node.getParentNode();
  972. if (node.getNodeType() == Node.ELEMENT_NODE)
  973. {
  974. String elementName = node.getLocalName();
  975. // 4.20. notAllowed element
  976. if ("notAllowed".equals(elementName))
  977. {
  978. String parentName = parent.getLocalName();
  979. if ("attribute".equals(parentName) ||
  980. "list".equals(parentName) ||
  981. "group".equals(parentName) ||
  982. "interleave".equals(parentName) ||
  983. "oneOrMore".equals(parentName))
  984. {
  985. Node pp = parent.getParentNode();
  986. pp.insertBefore(node, parent);
  987. pp.removeChild(parent);
  988. transform2(node); // apply recursively
  989. return;
  990. }
  991. else if ("choice".equals(parentName))
  992. {
  993. Node p1 = getFirstChildElement(parent);
  994. Node p2 = getNextSiblingElement(p1);
  995. if (p1 == null || p2 == null)
  996. throw new GrammarException("choice does not have two " +
  997. "children");
  998. String p1Name = p1.getLocalName();
  999. String p2Name = p2.getLocalName();
  1000. Node pp = parent.getParentNode();
  1001. if ("notAllowed".equals(p1Name) &&
  1002. "notAllowed".equals(p2Name))
  1003. {
  1004. pp.insertBefore(p1, parent);
  1005. pp.removeChild(parent);
  1006. transform2(p1); //apply recursively
  1007. return;
  1008. }
  1009. else if ("notAllowed".equals(p1Name))
  1010. {
  1011. pp.insertBefore(p2, parent);
  1012. pp.removeChild(parent);
  1013. transform2(p2);
  1014. return;
  1015. }
  1016. else
  1017. {
  1018. pp.insertBefore(p1, parent);
  1019. pp.removeChild(parent);
  1020. transform2(p1);
  1021. return;
  1022. }
  1023. }
  1024. else if ("except".equals(parentName))
  1025. {
  1026. Node pp = parent.getParentNode();
  1027. pp.removeChild(parent);
  1028. return;
  1029. }
  1030. }
  1031. // 4.21. empty element
  1032. else if ("empty".equals(elementName))
  1033. {
  1034. String parentName = parent.getLocalName();
  1035. if ("group".equals(parentName) ||
  1036. "interleave".equals(parentName))
  1037. {
  1038. Node p1 = getFirstChildElement(parent);
  1039. Node p2 = getNextSiblingElement(p1);
  1040. if (p1 == null || p2 == null)
  1041. throw new GrammarException(parentName + " does not have " +
  1042. "two children");
  1043. String p1Name = p1.getLocalName();
  1044. String p2Name = p2.getLocalName();
  1045. Node pp = parent.getParentNode();
  1046. if ("empty".equals(p1Name) &&
  1047. "empty".equals(p2Name))
  1048. {
  1049. pp.insertBefore(p1, parent);
  1050. pp.removeChild(parent);
  1051. transform2(p1);
  1052. return;
  1053. }
  1054. else if ("empty".equals(p1Name))
  1055. {
  1056. pp.insertBefore(p2, parent);
  1057. pp.removeChild(parent);
  1058. transform2(p2);
  1059. return;
  1060. }
  1061. else
  1062. {
  1063. pp.insertBefore(p1, parent);
  1064. pp.removeChild(parent);
  1065. transform2(p1);
  1066. return;
  1067. }
  1068. }
  1069. else if ("choice".equals(parentName))
  1070. {
  1071. Node p1 = getFirstChildElement(parent);
  1072. Node p2 = getNextSiblingElement(p1);
  1073. if (p1 == null || p2 == null)
  1074. throw new GrammarException(parentName + " does not have " +
  1075. "two children");
  1076. String p1Name = p1.getLocalName();
  1077. String p2Name = p2.getLocalName();
  1078. Node pp = parent.getParentNode();
  1079. if ("empty".equals(p1Name) &&
  1080. "empty".equals(p2Name))
  1081. {
  1082. pp.insertBefore(p1, parent);
  1083. pp.removeChild(parent);
  1084. transform2(p1);
  1085. return;
  1086. }
  1087. }
  1088. else if ("oneOrMore".equals(parentName))
  1089. {
  1090. Node pp = parent.getParentNode();
  1091. pp.insertBefore(node, parent);
  1092. pp.removeChild(parent);
  1093. transform2(node);
  1094. return;
  1095. }
  1096. }
  1097. Node ctx = node.getFirstChild();
  1098. while (ctx != null)
  1099. {
  1100. Node next = ctx.getNextSibling();
  1101. transform2(ctx);
  1102. ctx = next;
  1103. }
  1104. }
  1105. }
  1106. private static boolean isWhitespace(String text)
  1107. {
  1108. int len = text.length();
  1109. for (int i = 0; i < len; i++)
  1110. {
  1111. char c = text.charAt(i);
  1112. if (c != ' ' && c != '\t' && c != '\n' && c != '\r')
  1113. return false;
  1114. }
  1115. return true;
  1116. }
  1117. private static String escapeURL(String url)
  1118. {
  1119. try
  1120. {
  1121. return URLEncoder.encode(url, "UTF-8");
  1122. }
  1123. catch (UnsupportedEncodingException e)
  1124. {
  1125. RuntimeException e2 = new RuntimeException("UTF-8 is unsupported");
  1126. e2.initCause(e);
  1127. throw e2;
  1128. }
  1129. }
  1130. /**
  1131. * Resolve a URL to an element, as described in section 4.5.
  1132. */
  1133. private static Element resolve(String url)
  1134. throws IOException
  1135. {
  1136. try
  1137. {
  1138. URL u = new URL(url);
  1139. InputStream in = u.openStream();
  1140. DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
  1141. f.setNamespaceAware(true);
  1142. f.setCoalescing(true);
  1143. f.setExpandEntityReferences(true);
  1144. f.setIgnoringComments(true);
  1145. f.setIgnoringElementContentWhitespace(true);
  1146. DocumentBuilder b = f.newDocumentBuilder();
  1147. Document doc = b.parse(in, url);
  1148. in.close();
  1149. String fragment = u.getRef();
  1150. if (fragment != null)
  1151. return doc.getElementById(fragment);
  1152. return doc.getDocumentElement();
  1153. }
  1154. catch (SAXException e)
  1155. {
  1156. IOException e2 = new IOException("error parsing included element");
  1157. e2.initCause(e);
  1158. throw e2;
  1159. }
  1160. catch (ParserConfigurationException e)
  1161. {
  1162. IOException e2 = new IOException("error parsing included element");
  1163. e2.initCause(e);
  1164. throw e2;
  1165. }
  1166. }
  1167. /**
  1168. * Returns the "components" of an element, as described in section 4.7.
  1169. */
  1170. private List getComponents(Node node)
  1171. {
  1172. List ret = new LinkedList();
  1173. for (Node ctx = node.getFirstChild(); ctx != null;
  1174. ctx = ctx.getNextSibling())
  1175. {
  1176. if (ctx.getNodeType() != Node.ELEMENT_NODE)
  1177. continue;
  1178. String ns = ctx.getNamespaceURI();
  1179. if (ns != null && !ns.equals(XMLConstants.RELAXNG_NS_URI))
  1180. continue;
  1181. String name = ctx.getLocalName();
  1182. if ("div".equals(name))
  1183. ret.addAll(getComponents(ctx));
  1184. else if (VOCABULARY.containsKey(name))
  1185. ret.add(ctx);
  1186. }
  1187. return ret;
  1188. }
  1189. private static void transformToOneChildElement(Node node, String name)
  1190. {
  1191. if (node.getChildNodes().getLength() < 2)
  1192. return;
  1193. Document doc = node.getOwnerDocument();
  1194. Element child = doc.createElementNS(XMLConstants.RELAXNG_NS_URI, name);
  1195. Node ctx = getFirstChildElement(node);
  1196. while (ctx != null)
  1197. {
  1198. Node next = getNextSiblingElement(ctx);
  1199. child.appendChild(ctx);
  1200. ctx = next;
  1201. }
  1202. node.appendChild(child);
  1203. }
  1204. private static Element getFirstChildElement(Node node)
  1205. {
  1206. Node ctx = node.getFirstChild();
  1207. while (ctx != null && ctx.getNodeType() != Node.ELEMENT_NODE)
  1208. ctx = ctx.getNextSibling();
  1209. return (Element) ctx;
  1210. }
  1211. private static Element getNextSiblingElement(Node node)
  1212. {
  1213. Node ctx = node.getNextSibling();
  1214. while (ctx != null && ctx.getNodeType() != Node.ELEMENT_NODE)
  1215. ctx = ctx.getNextSibling();
  1216. return (Element) ctx;
  1217. }
  1218. private static void forbidDescendants(Node node, Set names)
  1219. throws GrammarException
  1220. {
  1221. for (Node ctx = node.getFirstChild(); ctx != null;
  1222. ctx = ctx.getNextSibling())
  1223. {
  1224. String ns = ctx.getNamespaceURI();
  1225. if (!XMLConstants.RELAXNG_NS_URI.equals(ns))
  1226. continue;
  1227. String name = ctx.getLocalName();
  1228. if (names.contains(name))
  1229. throw new GrammarException("name not allowed: " + name);
  1230. forbidDescendants(ctx, names);
  1231. }
  1232. }
  1233. private static boolean isDescendantOfFirstChildOfAttribute(Node node)
  1234. {
  1235. Node child = node;
  1236. Node parent = node.getParentNode();
  1237. while (parent != null && !"attribute".equals(parent.getLocalName()))
  1238. {
  1239. child = parent;
  1240. parent = child.getParentNode();
  1241. }
  1242. if (parent == null)
  1243. return false;
  1244. Node firstChild = getFirstChildElement(parent);
  1245. return firstChild == child;
  1246. }
  1247. private static void combineNodes(Node node, String combine, String name,
  1248. List nodes)
  1249. {
  1250. Document doc = node.getOwnerDocument();
  1251. Node child =
  1252. doc.createElementNS(XMLConstants.RELAXNG_NS_URI, name);
  1253. Node combineNode =
  1254. doc.createElementNS(XMLConstants.RELAXNG_NS_URI, combine);
  1255. child.appendChild(combineNode);
  1256. boolean inserted = false;
  1257. for (Iterator i = nodes.iterator(); i.hasNext(); )
  1258. {
  1259. Node startNode = (Node) i.next();
  1260. if (!inserted)
  1261. {
  1262. node.insertBefore(child, startNode);
  1263. inserted = true;
  1264. }
  1265. Node ctx = startNode.getFirstChild();
  1266. while (ctx != null)
  1267. {
  1268. Node next = ctx.getNextSibling();
  1269. combineNode.appendChild(ctx);
  1270. ctx = next;
  1271. }
  1272. node.removeChild(startNode);
  1273. }
  1274. }
  1275. Grammar parseGrammar(Element node)
  1276. throws GrammarException
  1277. {
  1278. checkName(node, "grammar");
  1279. Grammar grammar = new Grammar();
  1280. Element start = getFirstChildElement(node);
  1281. grammar.start = parsePattern(getFirstChildElement(start));
  1282. for (Element define = getNextSiblingElement(start); define != null;
  1283. define = getNextSiblingElement(define))
  1284. grammar.defines.add(parseDefine(define));
  1285. return grammar;
  1286. }
  1287. Define parseDefine(Element node)
  1288. throws GrammarException
  1289. {
  1290. checkName(node, "define");
  1291. Define define = new Define();
  1292. define.name = node.getAttribute("name");
  1293. define.element = parseElement(getFirstChildElement(node));
  1294. return define;
  1295. }
  1296. Pattern parseTop(Element node)
  1297. throws GrammarException
  1298. {
  1299. String name = node.getLocalName();
  1300. if ("notAllowed".equals(name))
  1301. return parseNotAllowed(node);
  1302. return parsePattern(node);
  1303. }
  1304. Pattern parsePattern(Element node)
  1305. throws GrammarException
  1306. {
  1307. String name = node.getLocalName();
  1308. if ("empty".equals(name))
  1309. return parseEmpty(node);
  1310. return parseNonEmptyPattern(node);
  1311. }
  1312. Pattern parseNonEmptyPattern(Element node)
  1313. throws GrammarException
  1314. {
  1315. String name = node.getLocalName();
  1316. if ("text".equals(name))
  1317. return parseText(node);
  1318. else if ("data".equals(name))
  1319. return parseData(node);
  1320. else if ("value".equals(name))
  1321. return parseValue(node);
  1322. else if ("list".equals(name))
  1323. return parseList(node);
  1324. else if ("attribute".equals(name))
  1325. return parseAttribute(node);
  1326. else if ("ref".equals(name))
  1327. return parseRef(node);
  1328. else if ("oneOrMore".equals(name))
  1329. return parseOneOrMore(node);
  1330. else if ("choice".equals(name))
  1331. return parseChoice(node);
  1332. else if ("group".equals(name))
  1333. return parseGroup(node);
  1334. else if ("interleave".equals(name))
  1335. return parseInterleave(node);
  1336. throw new GrammarException("invalid pattern: " + name);
  1337. }
  1338. ElementPattern parseElement(Element node)
  1339. throws GrammarException
  1340. {
  1341. checkName(node, "element");
  1342. ElementPattern element = new ElementPattern();
  1343. Element nameClass = getFirstChildElement(node);
  1344. element.nameClass = parseNameClass(nameClass);
  1345. element.pattern = parseTop(getNextSiblingElement(nameClass));
  1346. return element;
  1347. }
  1348. NotAllowedPattern parseNotAllowed(Element node)
  1349. throws GrammarException
  1350. {
  1351. checkName(node, "notAllowed");
  1352. return NotAllowedPattern.INSTANCE;
  1353. }
  1354. EmptyPattern parseEmpty(Element node)
  1355. throws GrammarException
  1356. {
  1357. checkName(node, "empty");
  1358. return EmptyPattern.INSTANCE;
  1359. }
  1360. TextPattern parseText(Element node)
  1361. throws GrammarException
  1362. {
  1363. checkName(node, "text");
  1364. return TextPattern.INSTANCE;
  1365. }
  1366. DataPattern parseData(Element node)
  1367. throws GrammarException
  1368. {
  1369. checkName(node, "data");
  1370. DataPattern data = new DataPattern();
  1371. DatatypeLibrary dl =
  1372. getDatatypeLibrary(node.getAttribute("datatypeLibrary"));
  1373. String type = node.getAttribute("type");
  1374. try
  1375. {
  1376. data.type = dl.createDatatype(type);
  1377. data.datatypeLibrary = dl;
  1378. }
  1379. catch (DatatypeException e)
  1380. {
  1381. GrammarException e2 = new GrammarException(type);
  1382. e2.initCause(e);
  1383. throw e2;
  1384. }
  1385. Element ctx = getFirstChildElement(node);
  1386. while (ctx != null)
  1387. {
  1388. Element next = getNextSiblingElement(ctx);
  1389. String name = ctx.getLocalName();
  1390. if ("param".equals(name))
  1391. data.params.add(parseParam(ctx));
  1392. else if ("except".equals(name) && next == null)
  1393. data.exceptPattern = parsePattern(getFirstChildElement(ctx));
  1394. else
  1395. throw new GrammarException("invalid element: " + name);
  1396. ctx = next;
  1397. }
  1398. return data;
  1399. }
  1400. Param parseParam(Element node)
  1401. throws GrammarException
  1402. {
  1403. checkName(node, "param");
  1404. Param param = new Param();
  1405. param.name = node.getAttribute("name");
  1406. param.value = node.getTextContent();
  1407. return param;
  1408. }
  1409. ValuePattern parseValue(Element node)
  1410. throws GrammarException
  1411. {
  1412. checkName(node, "value");
  1413. ValuePattern value = new ValuePattern();
  1414. DatatypeLibrary dl =
  1415. getDatatypeLibrary(node.getAttribute("datatypeLibrary"));
  1416. String type = node.getAttribute("type");
  1417. try
  1418. {
  1419. value.type = dl.createDatatype(type);
  1420. value.datatypeLibrary = dl;
  1421. }
  1422. catch (DatatypeException e)
  1423. {
  1424. GrammarException e2 = new GrammarException(type);
  1425. e2.initCause(e);
  1426. throw e2;
  1427. }
  1428. value.ns = node.getAttribute("ns");
  1429. value.value = node.getTextContent();
  1430. return value;
  1431. }
  1432. ListPattern parseList(Element node)
  1433. throws GrammarException
  1434. {
  1435. checkName(node, "list");
  1436. ListPattern list = new ListPattern();
  1437. list.pattern = parsePattern(getFirstChildElement(node));
  1438. return list;
  1439. }
  1440. AttributePattern parseAttribute(Element node)
  1441. throws GrammarException
  1442. {
  1443. checkName(node, "attribute");
  1444. AttributePattern attribute = new AttributePattern();
  1445. Element nameClass = getFirstChildElement(node);
  1446. attribute.nameClass = parseNameClass(nameClass);
  1447. attribute.pattern = parsePattern(getNextSiblingElement(nameClass));
  1448. return attribute;
  1449. }
  1450. RefPattern parseRef(Element node)
  1451. throws GrammarException
  1452. {
  1453. checkName(node, "ref");
  1454. RefPattern ref = new RefPattern();
  1455. ref.name = node.getAttribute("name");
  1456. return ref;
  1457. }
  1458. OneOrMorePattern parseOneOrMore(Element node)
  1459. throws GrammarException
  1460. {
  1461. checkName(node, "oneOrMore");
  1462. OneOrMorePattern oneOrMore = new OneOrMorePattern();
  1463. oneOrMore.pattern = parseNonEmptyPattern(getFirstChildElement(node));
  1464. return oneOrMore;
  1465. }
  1466. ChoicePattern parseChoice(Element node)
  1467. throws GrammarException
  1468. {
  1469. checkName(node, "choice");
  1470. ChoicePattern choice = new ChoicePattern();
  1471. Element p1 = getFirstChildElement(node);
  1472. Element p2 = getNextSiblingElement(p1);
  1473. choice.pattern1 = parsePattern(p1);
  1474. choice.pattern2 = parseNonEmptyPattern(p2);
  1475. return choice;
  1476. }
  1477. GroupPattern parseGroup(Element node)
  1478. throws GrammarException
  1479. {
  1480. checkName(node, "group");
  1481. GroupPattern group = new GroupPattern();
  1482. Element p1 = getFirstChildElement(node);
  1483. Element p2 = getNextSiblingElement(p1);
  1484. group.pattern1 = parseNonEmptyPattern(p1);
  1485. group.pattern2 = parseNonEmptyPattern(p2);
  1486. return group;
  1487. }
  1488. InterleavePattern parseInterleave(Element node)
  1489. throws GrammarException
  1490. {
  1491. checkName(node, "interleave");
  1492. InterleavePattern interleave = new InterleavePattern();
  1493. Element p1 = getFirstChildElement(node);
  1494. Element p2 = getNextSiblingElement(p1);
  1495. interleave.pattern1 = parseNonEmptyPattern(p1);
  1496. interleave.pattern2 = parseNonEmptyPattern(p2);
  1497. return interleave;
  1498. }
  1499. NameClass parseNameClass(Element node)
  1500. throws GrammarException
  1501. {
  1502. String name = node.getLocalName();
  1503. if ("anyName".equals(name))
  1504. return parseAnyName(node);
  1505. else if ("name".equals(name))
  1506. return parseName(node);
  1507. else if ("nsName".equals(name))
  1508. return parseNsName(node);
  1509. else if ("choice".equals(name))
  1510. return parseChoiceNameClass(node);
  1511. throw new GrammarException("invalid name class: " + name);
  1512. }
  1513. AnyNameNameClass parseAnyName(Element node)
  1514. throws GrammarException
  1515. {
  1516. checkName(node, "anyName");
  1517. AnyNameNameClass anyName = new AnyNameNameClass();
  1518. Element except = getFirstChildElement(node);
  1519. if (except != null) {
  1520. checkName(except, "except");
  1521. anyName.exceptNameClass = parseNameClass(getFirstChildElement(except));
  1522. }
  1523. return anyName;
  1524. }
  1525. NameNameClass parseName(Element node)
  1526. throws GrammarException
  1527. {
  1528. checkName(node, "name");
  1529. NameNameClass name = new NameNameClass();
  1530. name.ns = node.getAttribute("ns");
  1531. name.name = node.getTextContent();
  1532. return name;
  1533. }
  1534. NSNameNameClass parseNsName(Element node)
  1535. throws GrammarException
  1536. {
  1537. checkName(node, "nsName");
  1538. NSNameNameClass nsName = new NSNameNameClass();
  1539. nsName.ns = node.getAttribute("ns");
  1540. Element except = getFirstChildElement(node);
  1541. if (except != null) {
  1542. checkName(except, "except");
  1543. nsName.exceptNameClass = parseNameClass(getFirstChildElement(except));
  1544. }
  1545. return nsName;
  1546. }
  1547. ChoiceNameClass parseChoiceNameClass(Element node)
  1548. throws GrammarException
  1549. {
  1550. checkName(node, "choice");
  1551. ChoiceNameClass choice = new ChoiceNameClass();
  1552. Element c1 = getFirstChildElement(node);
  1553. Element c2 = getNextSiblingElement(c1);
  1554. choice.name1 = parseNameClass(c1);
  1555. choice.name2 = parseNameClass(c2);
  1556. return choice;
  1557. }
  1558. void checkName(Element node, String name)
  1559. throws GrammarException
  1560. {
  1561. if (!name.equals(node.getLocalName()))
  1562. throw new GrammarException("expecting " + name);
  1563. }
  1564. DatatypeLibrary getDatatypeLibrary(String uri)
  1565. throws GrammarException
  1566. {
  1567. if (datatypeLibraries == null)
  1568. datatypeLibraries = new HashMap();
  1569. DatatypeLibrary library = (DatatypeLibrary) datatypeLibraries.get(uri);
  1570. if (library == null)
  1571. {
  1572. library = new DatatypeLibraryLoader().createDatatypeLibrary(uri);
  1573. if (library == null)
  1574. throw new GrammarException("Datatype library not supported: " + uri);
  1575. datatypeLibraries.put(uri, library);
  1576. }
  1577. return library;
  1578. }
  1579. }