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("&", "&amp;");
        !          1449:     doc = doc.replaceAll("<", "&lt;");
        !          1450:     doc = doc.replaceAll(">", "&gt;");
        !          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>