Annotation of modules/damieng/graphical_editor/daxe/lib/src/config.dart, revision 1.1
1.1 ! damieng 1: /*
! 2: This file is part of Daxe.
! 3:
! 4: Daxe 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 3 of the License, or
! 7: (at your option) any later version.
! 8:
! 9: Daxe is distributed in the hope that it will be useful,
! 10: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 12: GNU General Public License for more details.
! 13:
! 14: You should have received a copy of the GNU General Public License
! 15: along with Daxe. If not, see <http://www.gnu.org/licenses/>.
! 16: */
! 17:
! 18: part of daxe;
! 19:
! 20:
! 21: /**
! 22: * A Jaxe configuration file. Includes many useful methods to use XML schemas.
! 23: */
! 24: class Config {
! 25: static final String _typeAffichageParDefaut = "string";
! 26:
! 27: x.Element _cfgroot; // config file root element
! 28:
! 29: String schemaURL; // schema file URL
! 30:
! 31: String _cfgdir; // config folder URL (in which the config file must be)
! 32:
! 33: HashMap<String, x.Element> _elementDisplayCache; // cache for associations nom -> AFFICHAGE_ELEMENT
! 34: HashMap<x.Element, String> _elementsToNamesCache; // cache for associations element reference -> name
! 35: HashMap<x.Element, String> _elementsTitlesCache; // cache for associations element reference -> title
! 36: HashMap<x.Element, Pattern> _insertCache = null; // cache for regular expressions for insertions
! 37: HashMap<x.Element, Pattern> _validPatternCache = null;
! 38: HashMap<x.Element, HashMap<String, List<String>>> _parametersCache = null;
! 39: List<String> _namespaceCache = null; // namespace list
! 40:
! 41: InterfaceSchema _schema; // all the schema management (validity...)
! 42:
! 43: // nodes for the config file main elements
! 44: x.Element _languageNode;
! 45: x.Element _savingNode;
! 46: x.Element _menusNode;
! 47: x.Element _displayNode;
! 48: x.Element _exportsNode;
! 49: List<x.Element> _listeStrings;
! 50:
! 51:
! 52: // CONSTRUCTORS AND INITIALIZATION
! 53:
! 54: /**
! 55: * Constructor (load must be called afterwards)
! 56: */
! 57: Config() {
! 58: }
! 59:
! 60: /**
! 61: * Load a config file
! 62: *
! 63: * @param cfgFilePath path to the config file
! 64: */
! 65: Future load(final String cfgFilePath) { // throws DaxeException
! 66: Completer completer = new Completer();
! 67: if (cfgFilePath == null) {
! 68: _cfgroot = null;
! 69: return(new Future.error(new DaxeException("Config.load: null path")));
! 70: }
! 71:
! 72: x.DOMParser dp = new x.DOMParser();
! 73: dp.parseFromURL(cfgFilePath).then((x.Document configdoc) {
! 74: String resource;
! 75: if (configdoc.documentElement.nodeName == "CONFIG_JAXE")
! 76: resource = null;
! 77: else
! 78: resource = _getResource(configdoc.documentElement);
! 79:
! 80: _cfgdir = _getParentURL(cfgFilePath);
! 81:
! 82: _cfgroot = configdoc.documentElement;
! 83:
! 84: // AUTRE_CONFIG: ignored
! 85:
! 86: _buildElementDisplayCache();
! 87:
! 88: _elementsTitlesCache = new HashMap<x.Element, String>();
! 89:
! 90: final String noms = schemaName();
! 91: if (noms == null) {
! 92: final x.Element schema_simple = _findElement(_getLanguage(), "SCHEMA_SIMPLE");
! 93: if (schema_simple == null) {
! 94: completer.completeError(new DaxeException("Error: no XML schema is defined in the config file $cfgFilePath"));
! 95: return;
! 96: }
! 97: _schema = new SimpleSchema(schema_simple, _titlesHash());
! 98: schemaURL = null;
! 99: _buildElementsToNamesCache();
! 100: completer.complete();
! 101: return;
! 102: }
! 103:
! 104: if (_cfgdir != null)
! 105: schemaURL = "${_cfgdir}/$noms";
! 106: else
! 107: schemaURL = noms;
! 108: _schema = new DaxeWXS(_titlesHash());
! 109: (_schema as DaxeWXS).load(schemaURL).then((_) {
! 110: _buildElementsToNamesCache();
! 111: completer.complete();
! 112: }, onError: (WXSException ex) {
! 113: completer.completeError(new DaxeException("Error reading schemaURL: $ex"));
! 114: });
! 115: }, onError: (x.DOMException ex) {
! 116: completer.completeError(new DaxeException("Error reading $cfgFilePath: $ex"));
! 117: });
! 118: return(completer.future);
! 119: }
! 120:
! 121: /**
! 122: * Returns the URL of the parent of the given URL (file or directory),
! 123: * or null if the parent directory cannot be found
! 124: */
! 125: static String _getParentURL(final String u) {
! 126: final int index = u.lastIndexOf("/");
! 127: if (index >= 0) {
! 128: return(u.substring(0, index));
! 129: }
! 130: return(null);
! 131: }
! 132:
! 133:
! 134: // METHODS RELATED TO THE CONFIG FILE
! 135:
! 136: /**
! 137: * Returns the name of the first possible root element, or null if none are defined.
! 138: */
! 139: String nameOfFirstRootElement() {
! 140: final x.Element racine = _findElement(_getLanguage(), "RACINE");
! 141: if (racine == null)
! 142: return(null);
! 143: return(racine.getAttribute("element"));
! 144: }
! 145:
! 146: /**
! 147: * Returns the reference to the first possible root element, or null if none are defined.
! 148: */
! 149: x.Element firstRootElement() {
! 150: final String nom = nameOfFirstRootElement();
! 151: return(_schema.elementReferenceByName(nom));
! 152: }
! 153:
! 154: /**
! 155: * Returns the list of names of the possible root elements
! 156: */
! 157: List<String> listOfRoots() {
! 158: final List<String> liste = new List<String>();
! 159: x.Element racine = _findElement(_getLanguage(), "RACINE");
! 160: while (racine != null) {
! 161: liste.add(racine.getAttribute("element"));
! 162: racine = _nextElement(racine, "RACINE");
! 163: }
! 164: return(liste);
! 165: }
! 166:
! 167: /**
! 168: * Returns the list of references to the possible root elements
! 169: */
! 170: List<x.Element> rootElements() {
! 171: // pour éviter une erreur dans le cas d'un schéma définissant un élément global et un élément local
! 172: // sous le même nom mais avec des types différents, on est obligé d'aller d'abord chercher les références
! 173: // des éléments racines en fonction de l'implémentation du schéma, puis de chercher dedans les éléments
! 174: // avec les noms donnés dans la config.
! 175: final List<x.Element> liste = new List<x.Element>();
! 176: final List<x.Element> racinesPossibles = _schema.rootElements();
! 177: x.Element racine = _findElement(_getLanguage(), "RACINE");
! 178: while (racine != null) {
! 179: final String nom = racine.getAttribute("element");
! 180: for (final x.Element ref in racinesPossibles)
! 181: if (nom == _schema.elementName(ref))
! 182: liste.add(ref);
! 183: racine = _nextElement(racine, "RACINE");
! 184: }
! 185: return(liste);
! 186: }
! 187:
! 188: /**
! 189: * Adds the attributes for the namespaces to the root node
! 190: */
! 191: void addNamespaceAttributes(final DaxeNode root) {
! 192: final List<String> espaces = _namespaceList();
! 193: for (final String espace in espaces) {
! 194: if (espace != "") {
! 195: final String prefixe = namespacePrefix(espace);
! 196: String nomatt;
! 197: if (prefixe != null && prefixe != "")
! 198: nomatt = "xmlns:$prefixe";
! 199: else
! 200: nomatt = "xmlns";
! 201: root.setAttributeNS("http://www.w3.org/2000/xmlns/", nomatt, espace);
! 202: }
! 203: }
! 204: final String schemaLocation = getSchemaLocation();
! 205: final String noNamespaceSchemaLocation = getNoNamespaceSchemaLocation();
! 206: if (schemaLocation != null || noNamespaceSchemaLocation != null) {
! 207: root.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
! 208: if (schemaLocation != null)
! 209: root.setAttributeNS("http://www.w3.org/2001/XMLSchema-instance",
! 210: "xsi:schemaLocation", schemaLocation);
! 211: if (noNamespaceSchemaLocation != null)
! 212: root.setAttributeNS("http://www.w3.org/2001/XMLSchema-instance",
! 213: "xsi:noNamespaceSchemaLocation", noNamespaceSchemaLocation);
! 214: }
! 215: }
! 216:
! 217: /**
! 218: * Returns the name of the schema file as given in the config file
! 219: * (FICHIER_SCHEMA/@nom)
! 220: * Returns null if none is defined
! 221: */
! 222: String schemaName() {
! 223: final x.Element fichierschema = _findElement(_getLanguage(), "FICHIER_SCHEMA");
! 224: if (fichierschema == null)
! 225: return(null);
! 226: String nom = fichierschema.getAttribute("nom");
! 227: if (nom == "")
! 228: nom = null;
! 229: return(nom);
! 230: }
! 231:
! 232: /**
! 233: * Returns the hash table by name of the element displays in the config file
! 234: * (element AFFICHAGE_ELEMENT)
! 235: */
! 236: HashMap<String, x.Element> _buildElementDisplayCache() {
! 237: _elementDisplayCache = new HashMap<String, x.Element>();
! 238: if (_cfgroot == null)
! 239: return(_elementDisplayCache);
! 240: x.Element affel = _findElement(_getNodeDisplay(), "AFFICHAGE_ELEMENT");
! 241: while (affel != null) {
! 242: final String nom = affel.getAttribute("element");
! 243: _elementDisplayCache[nom] = affel;
! 244: affel = _nextElement(affel, "AFFICHAGE_ELEMENT");
! 245: }
! 246: return(_elementDisplayCache);
! 247: }
! 248:
! 249: HashMap<x.Element, String> _getElementsToNamesCache() {
! 250: return(_elementsToNamesCache);
! 251: }
! 252:
! 253: x.Element getElementDisplay(String name) {
! 254: return _elementDisplayCache[name];
! 255: }
! 256:
! 257: /**
! 258: * Builds the hash table of associations schema reference -> element name
! 259: */
! 260: void _buildElementsToNamesCache() {
! 261: _elementsToNamesCache = new HashMap<x.Element, String>();
! 262: if (_cfgroot == null)
! 263: return;
! 264: final List<x.Element> elements = _schema.allElements();
! 265: for (final x.Element ref in elements) {
! 266: final String nom = _schema.elementName(ref);
! 267: if (nom != null)
! 268: _elementsToNamesCache[ref] = nom;
! 269: }
! 270: }
! 271:
! 272: /**
! 273: * Return the name of the resource bundle to use.
! 274: *
! 275: * @return the name of the resource bundle, null if not defined.
! 276: */
! 277: String _getResource(final x.Element root) {
! 278: final x.Element bundle = _findElement(root, "FICHIERTITRES");
! 279: if (bundle == null)
! 280: return(null);
! 281: return(bundle.getAttribute("nom"));
! 282: }
! 283:
! 284: /**
! 285: * Returns the list of export references, depending on the output (HTML or XML)
! 286: */
! 287: List<x.Element> exportsList(final String output) {
! 288: if (_cfgroot == null)
! 289: return(null);
! 290: final List<x.Element> liste = new List<x.Element>();
! 291: x.Element export = _findElement(_getExports(), "EXPORT");
! 292: while (export != null) {
! 293: if (output == export.getAttribute("sortie"))
! 294: liste.add(export);
! 295: export = _nextElement(export, "EXPORT");
! 296: }
! 297: return(liste);
! 298: }
! 299:
! 300: /**
! 301: * Returns an export name based on its reference
! 302: */
! 303: String exportName(final x.Element exportRef) {
! 304: return(exportRef.getAttribute("nom"));
! 305: }
! 306:
! 307: /**
! 308: * Returns the output of an export based on its reference
! 309: */
! 310: String exportOutput(final x.Element exportRef) {
! 311: return(exportRef.getAttribute("sortie"));
! 312: }
! 313:
! 314: /**
! 315: * Returns the character encoding to use for new XML documents
! 316: */
! 317: String getEncoding() {
! 318: final x.Element encodage = _findElement(_getSaving(), "ENCODAGE");
! 319: if (encodage == null)
! 320: return(null);
! 321: return(_dom_elementValue(encodage));
! 322: }
! 323:
! 324: String getPublicId() {
! 325: final x.Element doctype = _findElement(_getSaving(), "DOCTYPE");
! 326: if (doctype != null)
! 327: return doctype.getAttribute("publicId");
! 328:
! 329: return(null);
! 330: }
! 331:
! 332: String getSystemId() {
! 333: final x.Element doctype = _findElement(_getSaving(), "DOCTYPE");
! 334: if (doctype != null)
! 335: return doctype.getAttribute("systemId");
! 336: return(null);
! 337: }
! 338:
! 339: String getSchemaLocation() {
! 340: final x.Element sl = _findElement(_getSaving(), "SCHEMALOCATION");
! 341: if (sl != null) {
! 342: final String schemaLocation = sl.getAttribute("schemaLocation");
! 343: if (schemaLocation != "")
! 344: return(schemaLocation);
! 345: }
! 346: return(null);
! 347: }
! 348:
! 349: String getNoNamespaceSchemaLocation() {
! 350: final x.Element sl = _findElement(_getSaving(), "SCHEMALOCATION");
! 351: if (sl != null) {
! 352: final String noNamespaceSchemaLocation = sl.getAttribute("noNamespaceSchemaLocation");
! 353: if (noNamespaceSchemaLocation != "")
! 354: return(noNamespaceSchemaLocation);
! 355: }
! 356: return(null);
! 357: }
! 358:
! 359: /**
! 360: * Returns a prefix to use for the given namespace, or null if none is found
! 361: */
! 362: String namespacePrefix(final String namespace) {
! 363: if (namespace == "http://www.w3.org/XML/1998/namespace")
! 364: return("xml");
! 365: x.Element pe = _findElement(_getSaving(), "PREFIXE_ESPACE");
! 366: while (pe != null) {
! 367: if (namespace == pe.getAttribute("uri"))
! 368: return(pe.getAttribute("prefixe"));
! 369: pe = _nextElement(pe, "PREFIXE_ESPACE");
! 370: }
! 371: return(_schema.namespacePrefix(namespace));
! 372: }
! 373:
! 374:
! 375: // METHODS FOR THE ELEMENT INSERT MENUS
! 376:
! 377: /**
! 378: * Returns a menu matching the menu definition in the config file.
! 379: *
! 380: * @param doc The Daxe document
! 381: * @param menudef The MENU element in the config file
! 382: */
! 383: Menu _creationMenu(final DaxeDocument doc, final x.Element menudef) {
! 384: final String nomMenu = menudef.getAttribute("nom");
! 385: String titreM = menuTitle(nomMenu);
! 386: final Menu menu = new Menu(titreM);
! 387: String docMenu = menuDocumentation(nomMenu);
! 388: if (docMenu != null) {
! 389: //docMenu = "<html><body>{docMenu.replaceAll('\n', '<br>')}</body></html>";
! 390: menu.toolTipText = docMenu;
! 391: }
! 392: x.Node menunode = menudef.firstChild;
! 393: while (menunode != null) {
! 394: MenuItem item = null;
! 395: final String nodename = menunode.nodeName;
! 396: String shortcut = null;
! 397: if (menunode is x.Element) {
! 398: final String commande = (menunode as x.Element).getAttribute("raccourci");
! 399: if (commande != null && commande != "") {
! 400: shortcut = commande.toUpperCase()[0];
! 401: }
! 402: }
! 403: if (nodename == "MENU_INSERTION") {
! 404: final x.Element insnoeud = menunode as x.Element;
! 405: final String nom = insnoeud.getAttribute("nom");
! 406: final String titre = menuTitle(nom);
! 407: String typeNoeud = insnoeud.getAttribute("type_noeud");
! 408: if (typeNoeud == "")
! 409: typeNoeud = "element";
! 410: x.Element refElement;
! 411: if (typeNoeud == "element") {
! 412: refElement = elementReference(nom);
! 413: if (refElement == null)
! 414: logError("Erreur: MENU_INSERTION: pas de référence pour '$nom' dans le schéma");
! 415: } else
! 416: refElement = null;
! 417: item = new MenuItem(titre, () => doc.insertNewNode(refElement, typeNoeud), shortcut: shortcut, data: refElement);
! 418: menu.add(item);
! 419: String itemdoc = documentation(refElement);
! 420: if (itemdoc != null) {
! 421: //itemdoc = formatDoc(itemdoc);
! 422: item.toolTipText = itemdoc;
! 423: }
! 424: } else if (nodename == "MENU_FONCTION") {
! 425: final x.Element fonction = menunode as x.Element;
! 426: final String classe = fonction.getAttribute("classe");
! 427: final String nom = fonction.getAttribute("nom");
! 428: final String titre = menuTitle(nom);
! 429: item = new MenuItem(titre, () => doc.executeFunction(classe, fonction), shortcut: shortcut);
! 430: menu.add(item);
! 431: String itemdoc = menuDocumentation(nom);
! 432: if (itemdoc != null) {
! 433: //itemdoc = formatDoc(itemdoc);
! 434: item.toolTipText = itemdoc;
! 435: }
! 436: } else if (nodename == "MENU") {
! 437: item = _creationMenu(doc, menunode as x.Element);
! 438: menu.add(item);
! 439: } else if (nodename == "SEPARATEUR")
! 440: menu.addSeparator();
! 441:
! 442: menunode = menunode.nextSibling;
! 443: }
! 444: return(menu);
! 445: }
! 446:
! 447: /**
! 448: * Returns a menubar to insert menus.
! 449: *
! 450: * @param doc The Daxe document
! 451: */
! 452: MenuBar makeMenus(final DaxeDocument doc) {
! 453: final MenuBar mbar = new MenuBar();
! 454:
! 455: final x.Element menus = _getMenus();
! 456: if (menus != null) {
! 457: x.Element menudef = _findElement(menus, "MENU");
! 458: while (menudef != null) {
! 459: final Menu jmenu = _creationMenu(doc, menudef);
! 460: jmenu.parent = mbar;
! 461: mbar.add(jmenu);
! 462: menudef = _nextElement(menudef, "MENU");
! 463: }
! 464: }
! 465: return(mbar);
! 466: }
! 467:
! 468:
! 469: // METHODS RELATED TO THE SCHEMA
! 470:
! 471: InterfaceSchema getSchema() {
! 472: return(_schema);
! 473: }
! 474:
! 475: /**
! 476: * Returns the references for all the elements in the schema
! 477: */
! 478: List<x.Element> allElementsList() {
! 479: final List<x.Element> liste = _schema.allElements();
! 480: return(liste);
! 481: }
! 482:
! 483: bool _elementInSchema(final x.Element elementRef) {
! 484: return(_schema.elementInSchema(elementRef));
! 485: }
! 486:
! 487: /**
! 488: * Returns the name of the element
! 489: */
! 490: String elementName(final x.Element elementRef) {
! 491: return(_elementsToNamesCache[elementRef]);
! 492: }
! 493:
! 494: /**
! 495: * Returns the reference of the first matching element in the schema,
! 496: * based on the element and the reference of its parent
! 497: */
! 498: x.Element getElementRef(final x.Element el, final x.Element parentRef) {
! 499: return(_schema.elementReference(el, parentRef));
! 500: }
! 501:
! 502: /**
! 503: * Returns the reference for the first element with the given name
! 504: */
! 505: x.Element elementReference(final String name) {
! 506: final x.Element el = _schema.elementReferenceByName(localValue(name));
! 507: return(el);
! 508: }
! 509:
! 510: /**
! 511: * Returns the references of the elements with the given name
! 512: */
! 513: List<x.Element> elementReferences(final String name) {
! 514: return(_schema.elementReferencesByName(localValue(name)));
! 515: }
! 516:
! 517: /**
! 518: * Returns the namespace to use for the element,
! 519: * or null the namespace is undefined.
! 520: */
! 521: String elementNamespace(final x.Element elementRef) {
! 522: return(_schema.elementNamespace(elementRef));
! 523: }
! 524:
! 525: /**
! 526: * Returns the prefix to use for a new element with the given reference,
! 527: * or null if no prefix should be used.
! 528: */
! 529: String elementPrefix(final x.Element elementRef) {
! 530: final String espace = elementNamespace(elementRef);
! 531: if (espace == null)
! 532: return(null);
! 533: return(namespacePrefix(espace));
! 534: }
! 535:
! 536: /**
! 537: * Returns the list of possible values for an element.
! 538: * Returns null if there are an infinity of possible values.
! 539: */
! 540: List<String> elementValues(final x.Element elementRef) {
! 541: final List<String> liste = _schema.elementValues(elementRef);
! 542: return(liste);
! 543: }
! 544:
! 545: /**
! 546: * Returns true if the given value is valid for the element
! 547: */
! 548: bool isElementValueValid(final x.Element elementRef, final String value) {
! 549: return(_schema.elementValueIsValid(elementRef, value));
! 550: }
! 551:
! 552: /**
! 553: * Returns the list of all namespaces in the schema
! 554: */
! 555: List<String> _namespaceList() {
! 556: if (_namespaceCache != null)
! 557: return(_namespaceCache);
! 558: final List<String> liste = new List<String>();
! 559: final List<String> espacesSchema = _schema.namespaceList();
! 560: if (espacesSchema != null)
! 561: liste.addAll(espacesSchema);
! 562: _namespaceCache = liste;
! 563: return(liste);
! 564: }
! 565:
! 566: /**
! 567: * Returns a number for the given namespace, starting from 0.
! 568: * A unique number is given for each namespace.
! 569: * Returns -1 if the namespace is not found in the config.
! 570: */
! 571: int namespaceNumber(final String namespace) {
! 572: final List<String> liste = _namespaceList();
! 573: return(liste.indexOf(namespace));
! 574: }
! 575:
! 576: /**
! 577: * Returns true if the namspace is defined in the config
! 578: */
! 579: bool hasNamespace(final String namespace) {
! 580: return(_schema.hasNamespace(namespace));
! 581: }
! 582:
! 583: /**
! 584: * Returns the target namespace for the schema (targetNamespace attribute for WXS)
! 585: */
! 586: String targetNamespace() {
! 587: return(_schema.getTargetNamespace());
! 588: }
! 589:
! 590: /**
! 591: * Returns the references of the elements which are not in the given namespace
! 592: */
! 593: List<x.Element> elementsOutsideNamespace(final String namespace) {
! 594: return(_schema.elementsOutsideNamespace(namespace));
! 595: }
! 596:
! 597: /**
! 598: * Returns the references of the elements which are in the given namespaces
! 599: */
! 600: List<x.Element> elementsWithinNamespaces(final Set<String> namespaces) {
! 601: return(_schema.elementsWithinNamespaces(namespaces));
! 602: }
! 603:
! 604: /**
! 605: * Returns true if the child is required under the parent.
! 606: */
! 607: bool requiredElement(final x.Element parentRef, final x.Element childRef) {
! 608: return(_schema.requiredElement(parentRef, childRef));
! 609: }
! 610:
! 611: /**
! 612: * Returns true if there is a relation parent-child between the 2 elements
! 613: */
! 614: bool isSubElement(final x.Element parentRef, final x.Element childRef) {
! 615: final List<x.Element> children = subElements(parentRef);
! 616: if (children == null)
! 617: return(false);
! 618: return(children.contains(childRef));
! 619: }
! 620:
! 621: /**
! 622: * Returns the first reference in the list that is a child of the parent, or null if none is found.
! 623: */
! 624: x.Element findSubElement(final x.Element parentRef, final List<x.Element> refs) {
! 625: final List<x.Element> children = subElements(parentRef);
! 626: if (children == null)
! 627: return(null);
! 628: for (x.Element ref in refs)
! 629: if (children.contains(ref))
! 630: return(ref);
! 631: return(null);
! 632: }
! 633:
! 634: /**
! 635: * Returns true if the given name matches a possible child for the given parent
! 636: */
! 637: bool isSubElementByName(final x.Element parentRef, String childName) {
! 638: final int inds = childName.indexOf(':');
! 639: if (inds != -1)
! 640: childName = childName.substring(inds+1);
! 641: final List<String> noms = subElementsNames(parentRef);
! 642: return(noms.contains(childName));
! 643: }
! 644:
! 645: /**
! 646: * Returns the references of the given element's children
! 647: */
! 648: List<x.Element> subElements(final x.Element parentRef) {
! 649: return(_schema.subElements(parentRef));
! 650: }
! 651:
! 652: /**
! 653: * Returns the names of the given element's children
! 654: */
! 655: List<String> subElementsNames(final x.Element parentRef) {
! 656: final List<x.Element> listeReferences = subElements(parentRef);
! 657: final List<String> listeNoms = new List<String>();
! 658: for (final x.Element ref in listeReferences) {
! 659: final String nom = _elementsToNamesCache[ref];
! 660: if (!listeNoms.contains(nom))
! 661: listeNoms.add(nom);
! 662: }
! 663: return(listeNoms);
! 664: }
! 665:
! 666: /**
! 667: * Regular expression for a given element
! 668: * @param modevisu True to get a regular expression to display to the user
! 669: * @param modevalid For strict validation instead of checking if an insert is possible
! 670: */
! 671: String _regularExpression(final x.Element parentRef, final bool modevisu, final bool modevalid) {
! 672: return(_schema.regularExpression(parentRef, modevisu, modevalid));
! 673: }
! 674:
! 675: /**
! 676: * Regular expression based on the schema for a given parent element
! 677: */
! 678: String regularExpression(final x.Element parentRef) {
! 679: return(_schema.regularExpression(parentRef, true, false));
! 680: }
! 681:
! 682: /**
! 683: * Returns true if the toInsert element can be inserted under the parent element
! 684: * on the selection defined by the start and end positions
! 685: */
! 686: bool insertIsPossible(DaxeNode parent, final int startOffset, final int endOffset, final x.Element toInsert) {
! 687: if (parent.nodeType == DaxeNode.DOCUMENT_NODE) {
! 688: for (DaxeNode dn in parent.childNodes) {
! 689: if (dn.nodeType == DaxeNode.ELEMENT_NODE)
! 690: return(false);
! 691: }
! 692: return(true);
! 693: }
! 694: assert(parent.nodeType == DaxeNode.ELEMENT_NODE);
! 695: if (_schema is SimpleSchema)
! 696: return(true); // on suppose que le test de sous-élément a déjà été fait
! 697: if (startOffset < 0) {
! 698: logError("Config.insertionPossible: debutSelection < parent.debut");
! 699: return(false);
! 700: }
! 701: if (_schema is DaxeWXS) {
! 702: final List<x.Element> sousElements = new List<x.Element>();
! 703: bool ajoute = false;
! 704: for (DaxeNode dn = parent.firstChild; dn != null; dn = dn.nextSibling) {
! 705: if (dn.nodeType == DaxeNode.ELEMENT_NODE) {
! 706: int offset = parent.offsetOf(dn);
! 707: if (offset < startOffset || offset >= endOffset) {
! 708: if (!ajoute && offset >= endOffset) {
! 709: sousElements.add(toInsert);
! 710: ajoute = true;
! 711: }
! 712: sousElements.add(dn.ref);
! 713: }
! 714: }
! 715: }
! 716: if (!ajoute)
! 717: sousElements.add(toInsert);
! 718: final bool insertionOK = (_schema as DaxeWXS).validElement(parent.ref, sousElements, true);
! 719: return(insertionOK);
! 720: }
! 721: return(false);
! 722: /*
! 723: pb: on ne peut pas tester l'ordre des éléments dans certains cas, par exemple:
! 724: <html>
! 725: <head>
! 726: <xsl:if test='truc'>
! 727: <title>xxx</title>
! 728: </xsl:if>
! 729: <xsl:if test='not(truc)'>
! 730: <title>yyy</title>
! 731: </xsl:if>
! 732: </head>
! 733: </html>
! 734: Ici on autorise deux éléments title sous head alors qu'un seul est normalement autorisé.
! 735: Par contre on peut tester les imbrications (title est autorisé sous head).
! 736: */
! 737: }
! 738:
! 739: /**
! 740: * Returns true if the parent element is valid, considering its attributes,
! 741: * its first level children, its node value, and its parent if there is one.
! 742: */
! 743: bool elementIsValid(final DaxeNode parent) {
! 744: if (parent is DNComment || parent is DNProcessingInstruction || parent is DNCData)
! 745: return(true);
! 746:
! 747: if (parent.ref == null)
! 748: return(false);
! 749:
! 750: if (!attributesAreValid(parent))
! 751: return(false);
! 752:
! 753: if (parent.parent != null && parent.parent.ref != null && !isSubElement(parent.parent.ref, parent.ref))
! 754: return(false);
! 755:
! 756: if (parent.firstChild == null && !isElementValueValid(parent.ref, ''))
! 757: return(false);
! 758: else if (parent.childNodes.length == 1 && parent.firstChild is DNText && parent.firstChild.nodeValue != null &&
! 759: !isElementValueValid(parent.ref, parent.firstChild.nodeValue))
! 760: return(false);
! 761:
! 762: if (_schema is SimpleSchema)
! 763: return(true); // on suppose que le test de sous-balise a déjà été fait
! 764: if (_schema is DaxeWXS) {
! 765: final List<x.Element> sousElements = new List<x.Element>();
! 766: bool avectexte = false;
! 767: for (DaxeNode dn = parent.firstChild; dn != null; dn = dn.nextSibling) {
! 768: if (dn.nodeType == DaxeNode.ELEMENT_NODE && dn.ref != null) {
! 769: sousElements.add(dn.ref);
! 770: } else if (dn.nodeType == DaxeNode.TEXT_NODE) {
! 771: if (dn.nodeValue.trim() != "")
! 772: avectexte = true;
! 773: } else if (dn is DNCData) {
! 774: if (dn.firstChild != null && dn.firstChild.nodeValue.trim() != '')
! 775: avectexte = true;
! 776: }
! 777: }
! 778: if (avectexte && !_schema.canContainText(parent.ref))
! 779: return(false);
! 780: final DaxeWXS sch = _schema as DaxeWXS;
! 781: return(sch.validElement(parent.ref, sousElements, false));
! 782: }
! 783:
! 784: final x.Element refParent = parent.ref;
! 785: final StringBuffer cettexp = new StringBuffer();
! 786: if (_validPatternCache == null)
! 787: _validPatternCache = new HashMap<x.Element, Pattern>();
! 788:
! 789: bool avectexte = false;
! 790: DaxeNode child = parent.firstChild;
! 791: while (child != null) {
! 792: if (child is DNCData) {
! 793: if (child.firstChild != null && child.firstChild.nodeValue.trim() != '')
! 794: avectexte = true;
! 795: } else if (child.nodeType == DaxeNode.ELEMENT_NODE && child is! DNComment && child is! DNProcessingInstruction) {
! 796: cettexp.write(child.localName);
! 797: cettexp.write(",");
! 798: } else if (child.nodeType == DaxeNode.TEXT_NODE) {
! 799: if (child.nodeValue.trim() != '')
! 800: avectexte = true;
! 801: }
! 802: child = child.nextSibling;
! 803: }
! 804: if (avectexte && !_schema.canContainText(refParent))
! 805: return(false);
! 806: RegExp r = _validPatternCache[refParent];
! 807: if (r == null) {
! 808: final String expr = _regularExpression(refParent, false, true);
! 809: if (expr == null || expr == "")
! 810: return(true);
! 811: try {
! 812: r = new RegExp(r"^$expr$");
! 813: } on Exception catch(ex) {
! 814: logError("elementValide(JaxeElement, bool, List<String>) - Malformed Pattern: ^${expr}\$:", ex);
! 815: return(true);
! 816: }
! 817: _validPatternCache[refParent] = r;
! 818: }
! 819:
! 820: final bool matched = r.hasMatch(cettexp.toString());
! 821: return(matched);
! 822: }
! 823:
! 824: /**
! 825: * Returns true if the element attributes are valid and if there is not missing required attribute.
! 826: */
! 827: bool attributesAreValid(final DaxeNode dn) {
! 828: if (dn.nodeType != DaxeNode.ELEMENT_NODE) {
! 829: logError("Config.attributsValides : ce n'est pas un élément: $dn");
! 830: return(false);
! 831: }
! 832: // vérif des attributs qui sont dans le schéma
! 833: final List<x.Element> lattref = elementAttributes(dn.ref);
! 834: List<String> noms = new List<String>(lattref.length);
! 835: List<String> espaces = new List<String>(noms.length);
! 836: for (int i=0; i<lattref.length; i++) {
! 837: final x.Element attref = lattref[i];
! 838: noms[i] = attributeName(attref);
! 839: espaces[i] = attributeNamespace(attref);
! 840: final String valeur = dn.getAttribute(noms[i]);
! 841: if (valeur == null || valeur == '') {
! 842: if (requiredAttribute(dn.ref, attref))
! 843: return(false);
! 844: } else if (!validAttributeValue(attref, valeur))
! 845: return(false);
! 846: }
! 847: // vérif s'il y a des attributs en plus qui ne sont pas dans le schéma
! 848: final List<DaxeAttr> latt = dn.attributes;
! 849: for (int i=0; i<latt.length; i++) {
! 850: DaxeAttr att = latt[i];
! 851: final String prefixe = att.prefix;
! 852: if (prefixe == "xml" || prefixe == "xmlns")
! 853: continue;
! 854: final String nom = att.localName;
! 855: if (prefixe == null && nom == "xmlns")
! 856: continue;
! 857: final String espace = att.namespaceURI;
! 858: if (espace == "http://www.w3.org/2001/XMLSchema-instance")
! 859: continue;
! 860: bool trouve = false;
! 861: for (int j=0; j<noms.length; j++) {
! 862: if (noms[j] == nom && espaces[j] == espace) {
! 863: trouve = true;
! 864: break;
! 865: }
! 866: }
! 867: if (!trouve)
! 868: return(false);
! 869: }
! 870: return(true);
! 871: }
! 872:
! 873: /**
! 874: * Returns the list of possible parent elements for a given element
! 875: */
! 876: List<x.Element> parentElements(final x.Element elementRef) {
! 877: return(_schema.parentElements(elementRef));
! 878: }
! 879:
! 880: /**
! 881: * Returns the list of names for possible parent elements for a given element
! 882: */
! 883: List<String> parentNames(final x.Element elementRef) {
! 884: final List<x.Element> listeReferences = parentElements(elementRef);
! 885: final List<String> listeNoms = new List<String>();
! 886: for (final x.Element ref in listeReferences) {
! 887: final String nom = _elementsToNamesCache[ref];
! 888: if (!listeNoms.contains(nom))
! 889: listeNoms.add(nom);
! 890: }
! 891: return(listeNoms);
! 892: }
! 893:
! 894: /**
! 895: * Returns true if the given element can contain text
! 896: */
! 897: bool canContainText(final x.Element elementRef) {
! 898: if (elementRef == null)
! 899: return(true);
! 900: return(_schema.canContainText(elementRef));
! 901: }
! 902:
! 903: /**
! 904: * Returns the list of possible attributes for a given element.
! 905: */
! 906: List<x.Element> elementAttributes(final x.Element elementRef) {
! 907: return(_schema.elementAttributes(elementRef));
! 908: }
! 909:
! 910: /**
! 911: * Returns the name of an attribute based on its reference.
! 912: */
! 913: String attributeName(final x.Element attributeRef) {
! 914: return(_schema.attributeName(attributeRef));
! 915: }
! 916:
! 917: /**
! 918: * Returns the qualified name of an attribute based on its reference.
! 919: */
! 920: String attributeQualifiedName(final x.Element parentRef, final x.Element attributeRef) {
! 921: String name = _schema.attributeName(attributeRef);
! 922: String namespace = _schema.attributeNamespace(attributeRef);
! 923: if (namespace != null) {
! 924: String prefix = attributePrefix(parentRef, attributeRef);
! 925: if (prefix != null)
! 926: name = "$prefix:$name";
! 927: }
! 928: return(name);
! 929: }
! 930:
! 931: /**
! 932: * Returns an attribute namespace based on its reference, or null if none is defined.
! 933: */
! 934: String attributeNamespace(final x.Element attributeRef) {
! 935: return(_schema.attributeNamespace(attributeRef));
! 936: }
! 937:
! 938: /**
! 939: * Returns the prefix tu use to create an attribute, given the parent element and the attribute reference,
! 940: * or null if no prefix should be used.
! 941: */
! 942: String attributePrefix(final x.Element parent, final x.Element attributeRef) {
! 943: final String espace = attributeNamespace(attributeRef);
! 944: if (espace == null)
! 945: return(null);
! 946: if (espace == "http://www.w3.org/XML/1998/namespace")
! 947: return("xml");
! 948: if (espace == "http://www.w3.org/2000/xmlns/" && attributeName(attributeRef) != "xmlns")
! 949: return("xmlns");
! 950: // on essaye lookupPrefix avec le parent et avec son document
! 951: // (cas d'un élément en cours de création, pas encore inséré dans le document)
! 952: String prefixe = parent.lookupPrefix(espace);
! 953: if (prefixe == null) {
! 954: if (parent.ownerDocument.documentElement != null) // si l'élément racine existe
! 955: prefixe = parent.ownerDocument.lookupPrefix(espace);
! 956: else
! 957: prefixe = namespacePrefix(espace); // on suppose que la racine sera créée avec ajouterAttributsEspaces
! 958: }
! 959: return(prefixe);
! 960: }
! 961:
! 962: /**
! 963: * Returns an attribute namespace based on its full name (including the prefix).
! 964: */
! 965: String attributeNamespaceByName(final String name) {
! 966: return(_schema.attributeNamespaceByName(name));
! 967: }
! 968:
! 969: /**
! 970: * Returns true if the attribute is required for the parent element.
! 971: */
! 972: bool requiredAttribute(final x.Element parentRef, final x.Element attributeRef) {
! 973: return(_schema.attributeIsRequired(parentRef, attributeRef));
! 974: }
! 975:
! 976: /**
! 977: * Returns the list of possible values for an attribute.
! 978: * Returns null if there are an infinity of possible values.
! 979: */
! 980: List<String> attributeValues(final x.Element attributeRef) {
! 981: final List<String> liste = _schema.attributeValues(attributeRef);
! 982: return(liste);
! 983: }
! 984:
! 985: /**
! 986: * Returns an attribute's default value based on its reference.
! 987: */
! 988: String defaultAttributeValue(final x.Element attributeRef) {
! 989: return(_schema.defaultAttributeValue(attributeRef));
! 990: }
! 991:
! 992: /**
! 993: * Returns true if the given String is a valid value for the attribute.
! 994: */
! 995: bool validAttributeValue(final x.Element attributeRef, final String value) {
! 996: return(_schema.attributeIsValid(attributeRef, value));
! 997: }
! 998:
! 999: /**
! 1000: * Returns the local part of an element's name (by removing the prefix).
! 1001: */
! 1002: static String localValue(final String s) {
! 1003: if (s == null)
! 1004: return(null);
! 1005: final int ind = s.indexOf(':');
! 1006: if (ind == -1)
! 1007: return(s);
! 1008: return(s.substring(ind + 1));
! 1009: }
! 1010:
! 1011:
! 1012: // METHODS FOR DISPLAY TYPES
! 1013:
! 1014: /**
! 1015: * Returns a node display type based on the element reference, the node name and the DOM node type.
! 1016: */
! 1017: String nodeDisplayType(final x.Element elementRef, final String name, final int nodeType) {
! 1018: if (nodeType == x.Node.ELEMENT_NODE) {
! 1019: final x.Element affel = getElementDisplay(localValue(name));
! 1020: if (affel == null)
! 1021: return(_typeAffichageParDefaut);
! 1022: return(affel.getAttribute("type"));
! 1023: } else if (nodeType == x.Node.PROCESSING_INSTRUCTION_NODE) {
! 1024: x.Element elplug = _findElement(_getNodeDisplay(), "PLUGIN_INSTRUCTION");
! 1025: while (elplug != null) {
! 1026: if (name != null && name == elplug.getAttribute("cible"))
! 1027: return("plugin");
! 1028: elplug = _nextElement(elplug, "PLUGIN_INSTRUCTION");
! 1029: }
! 1030: return("instruction");
! 1031: } else if (nodeType == x.Node.COMMENT_NODE) {
! 1032: final x.Element elplug = _findElement(_getNodeDisplay(), "PLUGIN_COMMENTAIRE");
! 1033: if (elplug != null)
! 1034: return("plugin");
! 1035: return("commentaire");
! 1036: } else if (nodeType == x.Node.CDATA_SECTION_NODE) {
! 1037: final x.Element elplug = _findElement(_getNodeDisplay(), "PLUGIN_CDATA");
! 1038: if (elplug != null)
! 1039: return("plugin");
! 1040: return("cdata");
! 1041: } else if (nodeType == x.Node.TEXT_NODE) {
! 1042: return("texte");
! 1043: }
! 1044: return(null);
! 1045: }
! 1046:
! 1047: /**
! 1048: * Returns an element display type based on its reference.
! 1049: */
! 1050: String elementDisplayType(final x.Element elementRef) {
! 1051: final x.Element affel = getElementDisplay(elementName(elementRef));
! 1052: if (affel == null)
! 1053: return(_typeAffichageParDefaut);
! 1054: return(affel.getAttribute("type"));
! 1055: }
! 1056:
! 1057: /**
! 1058: * Returns the reference of the first element with the given display type in the config file.
! 1059: */
! 1060: x.Element firstElementWithType(final String displayType) {
! 1061: if (_cfgroot == null)
! 1062: return(null);
! 1063: x.Element affel = _findElement(_getNodeDisplay(), "AFFICHAGE_ELEMENT");
! 1064: while (affel != null) {
! 1065: if (displayType == affel.getAttribute("type"))
! 1066: return(elementReference(affel.getAttribute("element")));
! 1067: affel = _nextElement(affel, "AFFICHAGE_ELEMENT");
! 1068: }
! 1069: return(null);
! 1070: }
! 1071:
! 1072: /**
! 1073: * Returns the references of the elements with the given display type in the config file.
! 1074: */
! 1075: List<x.Element> elementsWithType(final String displayType) {
! 1076: if (_cfgroot == null)
! 1077: return(null);
! 1078: List<x.Element> list = new List<x.Element>();
! 1079: x.Element affel = _findElement(_getNodeDisplay(), "AFFICHAGE_ELEMENT");
! 1080: while (affel != null) {
! 1081: if (displayType == affel.getAttribute("type"))
! 1082: list.addAll(elementReferences(affel.getAttribute("element")));
! 1083: affel = _nextElement(affel, "AFFICHAGE_ELEMENT");
! 1084: }
! 1085: return(list);
! 1086: }
! 1087:
! 1088: /**
! 1089: * Returns the value of an element display parameter.
! 1090: * @param elementRef element reference
! 1091: * @param parameterName parameter name
! 1092: * @param defaultValue default value, used if the parameter is not found
! 1093: */
! 1094: String elementParameterValue(final x.Element elementRef, final String parameterName, final String defaultValue) {
! 1095: return nodeParameterValue(elementRef, "element", null, parameterName, defaultValue);
! 1096: }
! 1097:
! 1098: /**
! 1099: * Returns the value of a node display parameter.
! 1100: * The node type can be used to find display parameters for comments or PIs.
! 1101: */
! 1102: String nodeParameterValue(final x.Element elementRef, final String nodeType,
! 1103: final String name, final String parameterName, final String defaultValue) {
! 1104: final HashMap<String, List<String>> table = getNodeParameters(elementRef, nodeType, name);
! 1105: final List<String> lval = table[parameterName];
! 1106: String valeur;
! 1107: if (lval != null && lval.length > 0)
! 1108: valeur = lval[0];
! 1109: else
! 1110: valeur = defaultValue;
! 1111: return valeur;
! 1112: }
! 1113:
! 1114: /**
! 1115: * Returns a function parameter value.
! 1116: * @param fctdef Element for the function menu in the config file
! 1117: * @param parameterName parameter name
! 1118: * @param defaultValue default value, used if the parameter is not found
! 1119: */
! 1120: String functionParameterValue(final x.Element fctdef, final String parameterName, final String defaultValue) {
! 1121: x.Element parel = _findElement(fctdef, "PARAMETRE");
! 1122: while (parel != null) {
! 1123: final String nom = parel.getAttribute("nom");
! 1124: if (nom == parameterName)
! 1125: return(parel.getAttribute("valeur"));
! 1126: parel = _nextElement(parel, "PARAMETRE");
! 1127: }
! 1128: return(defaultValue);
! 1129: }
! 1130:
! 1131: HashMap<String, List<String>> _buildParameterCache(final x.Element base) {
! 1132: final HashMap<String, List<String>> hashparams = new HashMap<String, List<String>>();
! 1133: x.Element parel = _findElement(base, "PARAMETRE");
! 1134: while (parel != null) {
! 1135: final String nom = parel.getAttribute("nom");
! 1136: final String valeur = parel.getAttribute("valeur");
! 1137: List<String> lval = hashparams[nom];
! 1138: if (lval == null) {
! 1139: lval = new List<String>();
! 1140: lval.add(valeur);
! 1141: hashparams[nom] = lval;
! 1142: } else
! 1143: lval.add(valeur);
! 1144: parel = _nextElement(parel, "PARAMETRE");
! 1145: }
! 1146: _parametersCache[base] = hashparams;
! 1147: return(hashparams);
! 1148: }
! 1149:
! 1150: /**
! 1151: * Returns the table of an element display parameters.
! 1152: */
! 1153: HashMap<String, List<String>> getElementParameters(final x.Element elementRef) {
! 1154: return(getNodeParameters(elementRef, "element", null));
! 1155: }
! 1156:
! 1157: /**
! 1158: * Returns the table of a node display parameters.
! 1159: * The name can be null if nodeType is "element" and elementRef is not null.
! 1160: */
! 1161: HashMap<String, List<String>> getNodeParameters(final x.Element elementRef, final String nodeType, final String name) {
! 1162: x.Element base;
! 1163: if (nodeType == "element")
! 1164: base = getElementDisplay(elementName(elementRef));
! 1165: else if (nodeType == "instruction") {
! 1166: base = null;
! 1167: x.Element elplug = _findElement(_getNodeDisplay(), "PLUGIN_INSTRUCTION");
! 1168: while (elplug != null) {
! 1169: if (name != null && name == elplug.getAttribute("cible")) {
! 1170: base = elplug;
! 1171: break;
! 1172: }
! 1173: elplug = _nextElement(elplug, "PLUGIN_INSTRUCTION");
! 1174: }
! 1175: } else if (nodeType == "commentaire") {
! 1176: final x.Element elplug = _findElement(_getNodeDisplay(), "PLUGIN_COMMENTAIRE");
! 1177: if (elplug == null) {
! 1178: base = null;
! 1179: } else {
! 1180: base = elplug;
! 1181: }
! 1182: } else
! 1183: base = null;
! 1184: if (base == null)
! 1185: return(new HashMap<String, List<String>>());
! 1186: if (_parametersCache == null)
! 1187: _parametersCache = new HashMap<x.Element, HashMap<String, List<String>>>();
! 1188: HashMap<String, List<String>> hashparams = _parametersCache[base];
! 1189: if (hashparams == null)
! 1190: hashparams = _buildParameterCache(base);
! 1191: return(hashparams);
! 1192: }
! 1193:
! 1194: /**
! 1195: * Returns the list of suggested values for a given element.
! 1196: * Returns null if there is no suggestion.
! 1197: */
! 1198: List<String> elementSuggestedValues(final x.Element elementRef) {
! 1199: final Set<String> set = new LinkedHashSet<String>();
! 1200: List<String> schemaSuggestions = _schema.suggestedElementValues(elementRef);
! 1201: if (schemaSuggestions != null)
! 1202: set.addAll(_schema.suggestedElementValues(elementRef));
! 1203: final x.Element affel = getElementDisplay(elementName(elementRef));
! 1204: if (affel != null) {
! 1205: x.Element vs = _findElement(affel, "VALEUR_SUGGEREE");
! 1206: while (vs != null) {
! 1207: final String v = _dom_elementValue(vs);
! 1208: if (v != null)
! 1209: set.add(v);
! 1210: vs = _nextElement(vs, "VALEUR_SUGGEREE");
! 1211: }
! 1212: }
! 1213: if (set.length == 0)
! 1214: return(null);
! 1215: else
! 1216: return(set.toList());
! 1217: }
! 1218:
! 1219: /**
! 1220: * Returns the list of suggested values for an attribute,
! 1221: * based on the parent element reference and the attribute reference.
! 1222: * Returns null if there is no suggestion.
! 1223: */
! 1224: List<String> attributeSuggestedValues(final x.Element parentRef, final x.Element attributeRef) {
! 1225: final Set<String> set = new LinkedHashSet<String>();
! 1226: List<String> schemaSuggestions = _schema.suggestedAttributeValues(attributeRef);
! 1227: if (schemaSuggestions != null)
! 1228: set.addAll(schemaSuggestions);
! 1229: final x.Element affel = getElementDisplay(elementName(parentRef));
! 1230: if (affel != null) {
! 1231: final String nomAtt = attributeName(attributeRef);
! 1232: x.Element aa = _findElement(affel, "AFFICHAGE_ATTRIBUT");
! 1233: while (aa != null) {
! 1234: if (aa.getAttribute("attribut") == nomAtt) {
! 1235: x.Element vs = _findElement(aa, "VALEUR_SUGGEREE");
! 1236: while (vs != null) {
! 1237: final String v = _dom_elementValue(vs);
! 1238: if (v != null)
! 1239: set.add(v);
! 1240: vs = _nextElement(vs, "VALEUR_SUGGEREE");
! 1241: }
! 1242: }
! 1243: aa = _nextElement(aa, "AFFICHAGE_ATTRIBUT");
! 1244: }
! 1245: }
! 1246: if (set.length == 0)
! 1247: return(null);
! 1248: else
! 1249: return(set.toList());
! 1250: }
! 1251:
! 1252:
! 1253: // METHODS FOR THE STRINGS
! 1254:
! 1255: /**
! 1256: * Returns a list of the STRINGS elements in the config file,
! 1257: * ordered by preference based on the user language and country.
! 1258: */
! 1259: List<x.Element> _stringsElements() {
! 1260: final Locale defaut = new Locale();
! 1261: final List<x.Element> liste = new List<x.Element>();
! 1262:
! 1263: final List<x.Element> lstrings = _getStrings();
! 1264: for (final x.Element strings in lstrings) {
! 1265: final String langue = strings.getAttribute("langue");
! 1266: if (langue != "") {
! 1267: Locale strloc;
! 1268: if (strings.getAttribute("pays") == "")
! 1269: strloc = new Locale.l(langue);
! 1270: else
! 1271: strloc = new Locale.lc(langue, strings.getAttribute("pays"));
! 1272: if (defaut == strloc && !liste.contains(strings))
! 1273: liste.add(strings);
! 1274: }
! 1275: }
! 1276: for (final x.Element strings in lstrings) {
! 1277: final String langue = strings.getAttribute("langue");
! 1278: if (langue != "") {
! 1279: final Locale test = new Locale.lc(defaut.language, defaut.country);
! 1280: Locale strloc;
! 1281: if (strings.getAttribute("pays") == "")
! 1282: strloc = new Locale.l(langue);
! 1283: else
! 1284: strloc = new Locale.lc(langue, strings.getAttribute("pays"));
! 1285: if (test == strloc && !liste.contains(strings))
! 1286: liste.add(strings);
! 1287: }
! 1288: }
! 1289: for (final x.Element strings in lstrings) {
! 1290: final String langue = strings.getAttribute("langue");
! 1291: if (langue != "") {
! 1292: final Locale test = new Locale.l(defaut.language);
! 1293: if (test == new Locale.l(langue) && !liste.contains(strings))
! 1294: liste.add(strings);
! 1295: }
! 1296: }
! 1297: for (final x.Element strings in lstrings) {
! 1298: if (!liste.contains(strings))
! 1299: liste.add(strings);
! 1300: }
! 1301: return(liste);
! 1302: }
! 1303:
! 1304: /**
! 1305: * Returns the config description (element DESCRIPTION_CONFIG).
! 1306: */
! 1307: String description() {
! 1308: final List<x.Element> lstrings = _stringsElements();
! 1309: for (final x.Element strings in lstrings) {
! 1310: final x.Element descel = _findElement(strings, "DESCRIPTION_CONFIG");
! 1311: if (descel == null || descel.firstChild == null)
! 1312: break;
! 1313: String desc = _dom_elementValue(descel);
! 1314: return(desc);
! 1315: }
! 1316: return(null);
! 1317: }
! 1318:
! 1319: /**
! 1320: * Returns a menu title based on its name
! 1321: */
! 1322: String menuTitle(final String name) {
! 1323: final List<x.Element> lstrings = _stringsElements();
! 1324: for (final x.Element strings in lstrings) {
! 1325: x.Element sm = _findElementDeep(strings, "STRINGS_MENU");
! 1326: while (sm != null) {
! 1327: if (name == sm.getAttribute("menu")) {
! 1328: final x.Element eltitre = _findElement(sm, "TITRE");
! 1329: if (eltitre != null && eltitre.firstChild != null) {
! 1330: return(_dom_elementValue(eltitre));
! 1331: }
! 1332: break;
! 1333: }
! 1334: sm = _nextElementDeep(strings, sm, "STRINGS_MENU");
! 1335: }
! 1336: }
! 1337: final x.Element refel = elementReference(name);
! 1338: if (refel != null)
! 1339: return(elementTitle(refel));
! 1340: return(name);
! 1341: }
! 1342:
! 1343: /**
! 1344: * Returns a menu documentation based on its name.
! 1345: */
! 1346: String menuDocumentation(final String name) {
! 1347: final List<x.Element> lstrings = _stringsElements();
! 1348: for (final x.Element strings in lstrings) {
! 1349: x.Element sm = _findElementDeep(strings, "STRINGS_MENU");
! 1350: while (sm != null) {
! 1351: if (name == sm.getAttribute("menu")) {
! 1352: final x.Element eldoc = _findElement(sm, "DOCUMENTATION");
! 1353: if (eldoc != null && eldoc.firstChild != null) {
! 1354: return(_dom_elementValue(eldoc));
! 1355: }
! 1356: break;
! 1357: }
! 1358: sm = _nextElementDeep(strings, sm, "STRINGS_MENU");
! 1359: }
! 1360: }
! 1361: return(null);
! 1362: }
! 1363:
! 1364: HashMap<String, String> _titlesHash() {
! 1365: HashMap<String, String> h = new HashMap<String, String>();
! 1366: final List<x.Element> lstrings = _stringsElements();
! 1367: for (final x.Element strings in lstrings) {
! 1368: x.Element sel = _findElement(strings, "STRINGS_ELEMENT");
! 1369: while (sel != null) {
! 1370: String nom = sel.getAttribute("element");
! 1371: if (h[nom] == null) {
! 1372: String titre = nom;
! 1373: final x.Element eltitre = _findElement(sel, "TITRE");
! 1374: if (eltitre != null && eltitre.firstChild != null)
! 1375: titre = _dom_elementValue(eltitre);
! 1376: h[nom] = titre;
! 1377: }
! 1378: sel = _nextElement(sel, "STRINGS_ELEMENT");
! 1379: }
! 1380: }
! 1381: return(h);
! 1382: }
! 1383:
! 1384: /**
! 1385: * Returns an element title based on its reference.
! 1386: */
! 1387: String elementTitle(final x.Element elementRef) {
! 1388: String titre = null;
! 1389: titre = _elementsTitlesCache[elementRef];
! 1390: if (titre != null)
! 1391: return(titre);
! 1392: final String nom = elementName(elementRef);
! 1393: if (nom == null) {
! 1394: logError("Config.elementTitle : no name for $elementRef");
! 1395: return(null);
! 1396: }
! 1397: final List<x.Element> lstrings = _stringsElements();
! 1398: for (final x.Element strings in lstrings) {
! 1399: if (titre == null) {
! 1400: x.Element sel = _findElement(strings, "STRINGS_ELEMENT");
! 1401: while (sel != null) {
! 1402: if (sel.getAttribute("element") == nom) {
! 1403: final x.Element eltitre = _findElement(sel, "TITRE");
! 1404: if (eltitre != null && eltitre.firstChild != null) {
! 1405: titre = _dom_elementValue(eltitre);
! 1406: break;
! 1407: }
! 1408: break;
! 1409: }
! 1410: sel = _nextElement(sel, "STRINGS_ELEMENT");
! 1411: }
! 1412: }
! 1413: }
! 1414: if (titre == null || titre == "")
! 1415: titre = nom;
! 1416: _elementsTitlesCache[elementRef] = titre;
! 1417: return(titre);
! 1418: }
! 1419:
! 1420: /**
! 1421: * Returns an element documentation
! 1422: */
! 1423: String documentation(final x.Element elementRef) {
! 1424: if (elementRef == null)
! 1425: return(null);
! 1426: final String nom = elementName(elementRef);
! 1427: final List<x.Element> lstrings = _stringsElements();
! 1428: for (final x.Element strings in lstrings) {
! 1429: x.Element sel = _findElement(strings, "STRINGS_ELEMENT");
! 1430: while (sel != null) {
! 1431: if (nom == sel.getAttribute("element")) {
! 1432: final x.Element eldoc = _findElement(sel, "DOCUMENTATION");
! 1433: if (eldoc != null && eldoc.firstChild != null)
! 1434: return(_dom_elementValue(eldoc));
! 1435: break;
! 1436: }
! 1437: sel = _nextElement(sel, "STRINGS_ELEMENT");
! 1438: }
! 1439: }
! 1440: return(_schema.elementDocumentation(elementRef));
! 1441: }
! 1442:
! 1443: /**
! 1444: * Formats the documentation in HTML.
! 1445: */
! 1446: static String formatDoc(final String documentation) {
! 1447: String doc = documentation;
! 1448: doc = doc.replaceAll("&", "&");
! 1449: doc = doc.replaceAll("<", "<");
! 1450: doc = doc.replaceAll(">", ">");
! 1451: /*
! 1452: if (doc.length > 100) {
! 1453: int p = 0;
! 1454: for (int i=0; i<doc.length; i++) {
! 1455: if (i-p > 90 && doc[i] == ' ') {
! 1456: doc = "${doc.substring(0, i)}\n${doc.substring(i+1)}";
! 1457: p = i;
! 1458: } else if (doc[i] == '\n')
! 1459: p = i;
! 1460: }
! 1461: }
! 1462: */
! 1463: doc = doc.replaceAll("\n", "<br>");
! 1464: return(doc);
! 1465: }
! 1466:
! 1467: /**
! 1468: * Returns the title for an element value, based on the element reference and the value.
! 1469: */
! 1470: String elementValueTitle(final x.Element elementRef, final String value) {
! 1471: final String nom = elementName(elementRef);
! 1472: final List<x.Element> lstrings = _stringsElements();
! 1473: final String langueSyst = (new Locale()).language;
! 1474: for (final x.Element strings in lstrings) {
! 1475: x.Element sel = _findElement(strings, "STRINGS_ELEMENT");
! 1476: while (sel != null) {
! 1477: if (sel.getAttribute("element") == nom) {
! 1478: x.Element eltitrev = _findElement(sel, "TITRE_VALEUR");
! 1479: while (eltitrev != null) {
! 1480: if (eltitrev.getAttribute("valeur") == value &&
! 1481: eltitrev.firstChild != null)
! 1482: return(_dom_elementValue(eltitrev));
! 1483: eltitrev = _nextElement(eltitrev, "TITRE_VALEUR");
! 1484: }
! 1485: break;
! 1486: }
! 1487: sel = _nextElement(sel, "STRINGS_ELEMENT");
! 1488: }
! 1489: // la langue est trouvée mais il n'y a pas de TITRE_VALEUR correspondant
! 1490: // -> on renvoie la vraie valeur plutôt que de chercher un titre
! 1491: // dans d'autres langues.
! 1492: final String langue = strings.getAttribute("langue");
! 1493: if (langue == langueSyst)
! 1494: return(value);
! 1495: }
! 1496: return(value);
! 1497: }
! 1498:
! 1499: /**
! 1500: * Returns an attribute title based on the parent element reference and the attribute reference.
! 1501: */
! 1502: String attributeTitle(final x.Element parentRef, final x.Element attributeRef) {
! 1503: final String nomEl = elementName(parentRef);
! 1504: final String nomAtt = attributeName(attributeRef);
! 1505: final List<x.Element> lstrings = _stringsElements();
! 1506: for (final x.Element strings in lstrings) {
! 1507: x.Element sel = _findElement(strings, "STRINGS_ELEMENT");
! 1508: while (sel != null) {
! 1509: if (sel.getAttribute("element") == nomEl) {
! 1510: x.Element sat = _findElement(sel, "STRINGS_ATTRIBUT");
! 1511: while (sat != null) {
! 1512: if (sat.getAttribute("attribut") == nomAtt) {
! 1513: final x.Element eltitre = _findElement(sat, "TITRE");
! 1514: if (eltitre != null && eltitre.firstChild != null)
! 1515: return(_dom_elementValue(eltitre));
! 1516: break;
! 1517: }
! 1518: sat = _nextElement(sat, "STRINGS_ATTRIBUT");
! 1519: }
! 1520: }
! 1521: sel = _nextElement(sel, "STRINGS_ELEMENT");
! 1522: }
! 1523: }
! 1524: final String prefixe = attributePrefix(parentRef, attributeRef);
! 1525: if (prefixe != null)
! 1526: return("$prefixe:$nomAtt");
! 1527: return(nomAtt);
! 1528: }
! 1529:
! 1530: /**
! 1531: * Returns the title for an attribute value, based on the parent element reference,
! 1532: * the attribute reference and the value.
! 1533: */
! 1534: String attributeValueTitle(final x.Element parentRef, final x.Element attributeRef, final String value) {
! 1535: final String nomEl = elementName(parentRef);
! 1536: final String nomAtt = attributeName(attributeRef);
! 1537: final List<x.Element> lstrings = _stringsElements();
! 1538: final String langueSyst = (new Locale()).language;
! 1539: for (final x.Element strings in lstrings) {
! 1540: x.Element sel = _findElement(strings, "STRINGS_ELEMENT");
! 1541: while (sel != null) {
! 1542: if (sel.getAttribute("element") == nomEl) {
! 1543: x.Element sat = _findElement(sel, "STRINGS_ATTRIBUT");
! 1544: while (sat != null) {
! 1545: if (sat.getAttribute("attribut") == nomAtt) {
! 1546: x.Element eltitrev = _findElement(sat, "TITRE_VALEUR");
! 1547: while (eltitrev != null) {
! 1548: if (eltitrev.getAttribute("valeur") == value &&
! 1549: eltitrev.firstChild != null)
! 1550: return(_dom_elementValue(eltitrev));
! 1551: eltitrev = _nextElement(eltitrev, "TITRE_VALEUR");
! 1552: }
! 1553: break;
! 1554: }
! 1555: sat = _nextElement(sat, "STRINGS_ATTRIBUT");
! 1556: }
! 1557: }
! 1558: sel = _nextElement(sel, "STRINGS_ELEMENT");
! 1559: }
! 1560: // la langue est trouvée mais il n'y a pas de TITRE_VALEUR correspondant
! 1561: // -> on renvoie la vraie valeur d'attribut plutôt que de chercher un titre
! 1562: // dans d'autres langues.
! 1563: final String langue = strings.getAttribute("langue");
! 1564: if (langue == langueSyst)
! 1565: return(value);
! 1566: }
! 1567: return(value);
! 1568: }
! 1569:
! 1570: /**
! 1571: * Returns an attribute's documentation based on the parent element reference and
! 1572: * the attribute reference.
! 1573: */
! 1574: String attributeDocumentation(final x.Element parentRef, final x.Element attributeRef) {
! 1575: final String nomEl = elementName(parentRef);
! 1576: final String nomAtt = attributeName(attributeRef);
! 1577: final List<x.Element> lstrings = _stringsElements();
! 1578: for (final x.Element strings in lstrings) {
! 1579: x.Element sel = _findElement(strings, "STRINGS_ELEMENT");
! 1580: while (sel != null) {
! 1581: if (sel.getAttribute("element") == nomEl) {
! 1582: x.Element sat = _findElement(sel, "STRINGS_ATTRIBUT");
! 1583: while (sat != null) {
! 1584: if (sat.getAttribute("attribut") == nomAtt) {
! 1585: final x.Element eldoc = _findElement(sat, "DOCUMENTATION");
! 1586: if (eldoc != null &&eldoc.firstChild != null)
! 1587: return(_dom_elementValue(eldoc));
! 1588: break;
! 1589: }
! 1590: sat = _nextElement(sat, "STRINGS_ATTRIBUT");
! 1591: }
! 1592: }
! 1593: sel = _nextElement(sel, "STRINGS_ELEMENT");
! 1594: }
! 1595: }
! 1596: return(_schema.attributeDocumentation(attributeRef));
! 1597: }
! 1598:
! 1599: /**
! 1600: * Returns an export's title based on its reference.
! 1601: */
! 1602: String exportTitle(final x.Element exportRef) {
! 1603: final String nom = exportName(exportRef);
! 1604: final List<x.Element> lstrings = _stringsElements();
! 1605: for (final x.Element strings in lstrings) {
! 1606: x.Element export = _findElement(strings, "STRINGS_EXPORT");
! 1607: while (export != null) {
! 1608: if (nom == export.getAttribute("export")) {
! 1609: final x.Element eltitre = _findElement(export, "TITRE");
! 1610: if (eltitre != null && eltitre.firstChild != null)
! 1611: return(_dom_elementValue(eltitre));
! 1612: break;
! 1613: }
! 1614: export = _nextElement(export, "STRINGS_EXPORT");
! 1615: }
! 1616: }
! 1617: return(nom);
! 1618: }
! 1619:
! 1620: /**
! 1621: * Returns an export's documentation based on its reference.
! 1622: */
! 1623: String exportDocumentation(final x.Element exportRef) {
! 1624: final String nom = exportName(exportRef);
! 1625: final List<x.Element> lstrings = _stringsElements();
! 1626: for (final x.Element strings in lstrings) {
! 1627: x.Element export = _findElement(strings, "STRINGS_EXPORT");
! 1628: while (export != null) {
! 1629: if (nom == export.getAttribute("export")) {
! 1630: final x.Element eldoc = _findElement(export, "DOCUMENTATION");
! 1631: if (eldoc != null && eldoc.firstChild != null)
! 1632: return(_dom_elementValue(eldoc));
! 1633: break;
! 1634: }
! 1635: export = _nextElement(export, "STRINGS_EXPORT");
! 1636: }
! 1637: }
! 1638: return(null);
! 1639: }
! 1640:
! 1641:
! 1642: // TOOLS
! 1643:
! 1644: /**
! 1645: * Returns the value of the first child node, removing leading and trailing whites.
! 1646: * Returns null if there is not child node.
! 1647: */
! 1648: static String _dom_elementValue(final x.Node el) {
! 1649: final x.Node fc = el.firstChild;
! 1650: if (fc == null)
! 1651: return(null);
! 1652: final String v = fc.nodeValue;
! 1653: if (v == null)
! 1654: return(null);
! 1655: return(v.trim());
! 1656: }
! 1657:
! 1658: x.Element _getLanguage() {
! 1659: if (_languageNode == null) {
! 1660: _languageNode = _findElement(_cfgroot, "LANGAGE");
! 1661: }
! 1662: return _languageNode;
! 1663: }
! 1664:
! 1665: x.Element _getSaving() {
! 1666: if (_savingNode == null) {
! 1667: _savingNode = _findElement(_cfgroot, "ENREGISTREMENT");
! 1668: if (_savingNode == null) {
! 1669: _savingNode = _cfgroot.ownerDocument.createElement("ENREGISTREMENT");
! 1670: }
! 1671: }
! 1672: return _savingNode;
! 1673: }
! 1674:
! 1675: x.Element _getMenus() {
! 1676: if (_menusNode == null) {
! 1677: _menusNode = _findElement(_cfgroot, "MENUS");
! 1678: if (_menusNode == null) {
! 1679: _menusNode = _cfgroot.ownerDocument.createElement("MENUS");
! 1680: }
! 1681: }
! 1682: return _menusNode;
! 1683: }
! 1684:
! 1685: x.Element _getNodeDisplay() {
! 1686: if (_displayNode == null) {
! 1687: _displayNode = _findElement(_cfgroot, "AFFICHAGE_NOEUDS");
! 1688: if (_displayNode == null) {
! 1689: _displayNode = _cfgroot.ownerDocument.createElement("AFFICHAGE_NOEUDS");
! 1690: }
! 1691: }
! 1692: return _displayNode;
! 1693: }
! 1694:
! 1695: x.Element _getExports() {
! 1696: if (_exportsNode == null) {
! 1697: _exportsNode = _findElement(_cfgroot, "EXPORTS");
! 1698: if (_exportsNode == null) {
! 1699: _exportsNode = _cfgroot.ownerDocument.createElement("EXPORTS");
! 1700: }
! 1701: }
! 1702: return _exportsNode;
! 1703: }
! 1704:
! 1705: List<x.Element> _getStrings() {
! 1706: if (_listeStrings == null) {
! 1707: _listeStrings = new List<x.Element>();
! 1708: x.Node child = _cfgroot.firstChild;
! 1709: while (child != null) {
! 1710: if (child.nodeType == x.Node.ELEMENT_NODE && child.nodeName == "STRINGS") {
! 1711: _listeStrings.add(child as x.Element);
! 1712: }
! 1713: child = child.nextSibling;
! 1714: }
! 1715: }
! 1716: return _listeStrings;
! 1717: }
! 1718:
! 1719:
! 1720: static x.Element _findElement(final x.Node n, final String name) {
! 1721: final x.Node child = n.firstChild;
! 1722: return _nextNode(child, name);
! 1723: }
! 1724:
! 1725: static x.Element _nextElement(final x.Node n, final String name) {
! 1726: final x.Node child = n.nextSibling;
! 1727: return _nextNode(child, name);
! 1728: }
! 1729:
! 1730: static x.Element _nextNode(x.Node child, final String name) {
! 1731: if (name == null)
! 1732: return null;
! 1733: while (child != null) {
! 1734: if (child.nodeType == x.Node.ELEMENT_NODE && name == child.nodeName) {
! 1735: return child as x.Element;
! 1736: }
! 1737: child = child.nextSibling;
! 1738: }
! 1739: return null;
! 1740: }
! 1741:
! 1742: static x.Element _findElementDeep(final x.Node n, final String name) {
! 1743: return _nextElementDeep(n, n, name);
! 1744: }
! 1745:
! 1746: static x.Element _nextElementDeep(final x.Node parent, final x.Node n, final String name) {
! 1747: x.Node current = n;
! 1748: x.Node next;
! 1749: while (current != null) {
! 1750: if (current.hasChildNodes()) {
! 1751: current = (current.firstChild);
! 1752: } else if (current != parent && null != (next = current.nextSibling)) {
! 1753: current = next;
! 1754: } else {
! 1755: next = null;
! 1756: while (current != parent) {
! 1757:
! 1758: next = current.nextSibling;
! 1759: if (next != null)
! 1760: break;
! 1761: current = current.parentNode;
! 1762: }
! 1763: current = next;
! 1764: }
! 1765: if (current != parent && current != null && current.nodeType == x.Node.ELEMENT_NODE
! 1766: && current.nodeName == name) {
! 1767: return current as x.Element;
! 1768: }
! 1769: }
! 1770: return null;
! 1771: }
! 1772:
! 1773: static void logError(String message, [Exception ex]) {
! 1774: if (ex != null)
! 1775: print("Config: $message: $ex");
! 1776: else
! 1777: print("Config: $message");
! 1778: }
! 1779: }
! 1780:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>