Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/gendiapo/editor/document/GenDiapoDocumentFactory.java


1   /*
2    * @(#)GenDiapoDocumentFactory.java  1.000 01/05/30 
3    */
4   package org.gendiapo.editor.document;
5   
6   import java.lang.reflect.Method;
7   
8   import java.awt.*;
9   import java.awt.event.*;
10  import java.io.*;
11  import java.beans.*;
12  import java.util.*;
13  
14  import javax.swing.*;
15  import javax.swing.text.*;
16  import javax.swing.text.html.*;
17  import javax.swing.event.*;
18  
19  import org.gendiapo.editor.*;
20  import org.gendiapo.editor.document.*;
21  
22  import org.merlotxml.merlot.*;
23  import org.merlotxml.util.xml.*;
24  
25  public class GenDiapoDocumentFactory {    
26      
27      static final ArrayList EMPTY = new ArrayList();
28      
29      static final Integer IntDummy          = new java.lang.Integer(GenDiapoDocument.Dummy);
30      static final Integer IntFragment       = new java.lang.Integer(org.w3c.dom.Node.DOCUMENT_FRAGMENT_NODE);
31      static final Integer IntAttribute      = new java.lang.Integer(org.w3c.dom.Node.ATTRIBUTE_NODE);    
32      static final Integer IntParagraph      = new java.lang.Integer(GenDiapoDocument.Paragraph);
33      static final Integer IntText           = new java.lang.Integer(GenDiapoDocument.Text);    
34      static final Integer IntParagraphCSS   = new java.lang.Integer(GenDiapoDocument.ParagraphCSS);
35      static final Integer IntTextCSS        = new java.lang.Integer(GenDiapoDocument.TextCSS);    
36      
37      static final GenDiapoDocument.ElementSpec EndElementSpec = new GenDiapoDocument.ElementSpec(null, GenDiapoDocument.ElementSpec.EndTagType);
38  
39      public GenDiapoDocumentFactory() {
40      }
41  
42      /*--- affichage des noeuds du document ----*/
43      public static void debugViewChild(String tab, Element element) {
44    if (!element.isLeaf()) {
45        // Child
46        int nb = element.getElementCount();
47        for (int i=0; i<nb; i++) {
48      Element eChild = element.getElement(i);
49      AttributeSet eAttr = eChild.getAttributes();
50      Object oStyle = eAttr.getAttribute(GenDiapoDocument.ATTRIBUT_STYLENAME);
51      String style = "";
52      if (oStyle instanceof String) {
53          style = (String) oStyle;
54      }
55      System.out.println(tab+eChild.getName()+"("+eChild.getStartOffset()+","+eChild.getEndOffset()+") style:"+style);
56      debugViewChild(tab+"   ",eChild);
57        }
58    }
59      }    
60          
61      static java.util.List getAttributesOrder(MerlotDOMNode node) {        
62          java.util.List order = EMPTY;
63    MerlotDOMEditor editor = node.getEditor();
64    if (editor instanceof GenDiapoEditor) {
65        if (editor != null) {
66      GenDiapoEditor genDiapoEditor = (GenDiapoEditor) editor;
67      order=genDiapoEditor.attributesInStyledView(node);
68        }       
69    }        
70          return order;
71      }
72      
73      static Map getDTDAttributes(MerlotDOMNode node) {
74          Map attributesMap = new Hashtable();
75          
76    Enumeration dtdAttributes = node.getDTDAttributes();  
77    if (dtdAttributes != null) {
78        DTDAttribute nodeAttr;      
79              
80        while (dtdAttributes.hasMoreElements()) {
81      nodeAttr = (DTDAttribute)dtdAttributes.nextElement();
82                  attributesMap.put(nodeAttr.getName(), nodeAttr);
83              }
84          }        
85          
86          return attributesMap;
87      }
88      
89      static java.util.List getDTDAttributesInStyledView(MerlotDOMNode node) {
90          java.util.List attributes = new ArrayList();
91          
92          // init        
93          java.util.List order = getAttributesOrder(node);        
94          Map attributesMap = getDTDAttributes(node);        
95          
96          // fill attributes
97          Iterator i = order.iterator();        
98          while (i.hasNext()) {
99              String attributeName = (String) i.next();            
100             Object dtdAttribute = attributesMap.get(attributeName);
101             if (dtdAttribute != null) {                
102                 attributes.add(dtdAttribute);
103             }
104         }
105         
106         return attributes;
107     }
108     
109     /*
110      * parseStringLF
111      * Ajoute autant de ParagraphElement que de ligne
112      * Suppose que le dernier caractère soit une retour a la ligne
113      */
114     static void parseStringLF(Vector change, String str, Style textStyle) {
115   char[] buf = str.toCharArray();
116   int lastLF = 0;
117   SimpleAttributeSet text_attr, para_attr;
118 
119   Object paragraphType, contentType;
120 
121   if (textStyle != null) {
122       paragraphType = IntParagraphCSS;
123       contentType   = IntTextCSS;
124   } else {
125       paragraphType = IntParagraph;
126       contentType   = IntText;
127   }
128 
129 
130   for (int i=0; i<buf.length; i++) {
131       if (buf[i] == '\n' ) {
132     // start paragraph
133     text_attr= new SimpleAttributeSet();
134     text_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, paragraphType);
135     if (textStyle != null) {
136         text_attr.addAttributes(textStyle);
137     }
138     change.add(new GenDiapoDocument.ElementSpec(text_attr, GenDiapoDocument.ElementSpec.StartTagType));
139     
140     // texte
141     para_attr= new SimpleAttributeSet();
142     para_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, contentType);
143     change.add(new GenDiapoDocument.ElementSpec(para_attr, 
144                   GenDiapoDocument.ElementSpec.ContentType, 
145                   buf,
146                   lastLF,
147                   i-lastLF+1));
148 
149     // end paragraph
150     change.add(EndElementSpec);
151     lastLF = i+1;
152       }
153   }
154     }
155 
156     /* 
157      * parseString
158      * Ajoute une seul ligne en remplacant tout les retour a ligne par un espace
159      */
160     static void parseString(Vector change, String str, Style textStyle) {
161 
162   char[] buf = str.toCharArray();
163   SimpleAttributeSet text_attr, para_attr;
164 
165   // remplace tous les '\n' par ' '
166   for(int i=0; i<(buf.length-1); i++) {
167       if (buf[i] == '\n') {
168     buf[i] = ' ';
169       }
170   }
171   
172   // start paragraph       
173   text_attr= new SimpleAttributeSet();  
174   Object paragraphType, contentType;
175   if (textStyle != null) {
176       text_attr.addAttributes(textStyle);
177       paragraphType = IntParagraphCSS;
178       contentType   = IntTextCSS;
179   } else {
180       paragraphType = IntParagraph;
181       contentType   = IntText;
182   }
183   text_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, paragraphType);
184   change.add(new GenDiapoDocument.ElementSpec(text_attr, GenDiapoDocument.ElementSpec.StartTagType));
185   
186   // texte
187   para_attr= new SimpleAttributeSet();
188   para_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, contentType);
189   change.add(new GenDiapoDocument.ElementSpec(para_attr, 
190                 GenDiapoDocument.ElementSpec.ContentType, 
191                 buf,
192                 0,
193                 buf.length));
194   // end paragraph
195   change.add(EndElementSpec);  
196     }
197 
198     static void addPCDataTree(Vector change, Object position) {
199   String text,str;
200   SimpleAttributeSet attr_attr;
201 
202   str = "\n";;
203   
204   // attribut
205   // xmlNode, MerlotNode herités
206   attr_attr= new SimpleAttributeSet();      
207   attr_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntFragment);
208   attr_attr.addAttribute(GenDiapoDocument.ATTRIBUT_MERLOTTEXT, position);
209   change.add(new GenDiapoDocument.ElementSpec(attr_attr, GenDiapoDocument.ElementSpec.StartTagType));
210   
211   // Ajout de la chaine de caractère
212   parseStringLF(change, str, null);
213   
214   // EndTag
215   change.add(EndElementSpec);
216     }
217     
218     static void parsePCDataTree(Vector change, MerlotDOMText node) {
219   String text,str;
220   SimpleAttributeSet attr_attr;
221 
222   str = node.getText()+"\n";;
223   
224   // attribut
225   // xmlNode, MerlotNode herités
226   attr_attr= new SimpleAttributeSet();      
227   attr_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntFragment);
228   attr_attr.addAttribute(GenDiapoDocument.ATTRIBUT_MERLOTTEXT, node);
229   change.add(new GenDiapoDocument.ElementSpec(attr_attr, GenDiapoDocument.ElementSpec.StartTagType));
230   
231   // Ajout de la chaine de caractère
232   parseStringLF(change, str, null);
233   
234   // EndTag
235   change.add(EndElementSpec);
236     }
237 
238 
239     static boolean pcDataAllowed(MerlotDOMNode node) {
240   org.w3c.dom.Node xmlNode = node.getRealNode();
241   Enumeration en = node.getAppendableElements();
242   DTDElement el;
243   String nm;
244   String text,str;
245   SimpleAttributeSet attr_attr, text_attr, para_attr;
246   
247   while (en != null && en.hasMoreElements()) {
248       el = (DTDElement)en.nextElement();
249       if (el != null) {
250     nm = el.getName();
251     if (nm != null && nm.equals(DTDConstants.PCDATA_KEY)) {
252         return true;
253     }
254       }
255   }
256   return false;
257     }
258 
259 
260     public static void parseAttributes(Vector change, MerlotDOMNode node, StyleSheet style) {
261         org.w3c.dom.Node xmlNode = node.getRealNode();        
262         java.util.List attributes = getDTDAttributesInStyledView(node);                
263         Iterator i = attributes.iterator();
264         while (i.hasNext()) {
265             DTDAttribute nodeAttr = (DTDAttribute)i.next();
266             
267             // Value
268             String attrValue="";
269             if (xmlNode instanceof org.w3c.dom.Element) {
270                 attrValue = ((org.w3c.dom.Element)xmlNode).getAttribute(nodeAttr.getName());
271             }
272             if (attrValue == null) {
273                 attrValue = "";
274             }            
275             attrValue += "\n";
276             
277             // Open AttributeSet
278             // XMLNODE, MERLOTNODE hérités
279             SimpleAttributeSet attr_attr= new SimpleAttributeSet();
280             attr_attr.addAttribute(GenDiapoDocument.ATTRIBUT_DTDATTRIBUTE, nodeAttr);
281             attr_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntAttribute);
282             change.add(new GenDiapoDocument.ElementSpec(attr_attr, GenDiapoDocument.ElementSpec.StartTagType));
283             
284             // Add string with style
285             Style textStyle;
286             if (style == null) {
287                 textStyle = null;
288             } else {
289                 textStyle = getStyleAttribute(style, node, nodeAttr);
290             }
291             parseString(change, attrValue, textStyle);
292             
293             // Close AttributeSet
294             change.add(EndElementSpec);
295         }        
296     }
297 
298     /**
299      * Utilise par parseGlobalElementTree
300      * @return Un ElementSpec de type ElementSpec.ContentType 
301      */
302     private static GenDiapoDocument.ElementSpec voidTextElementSpec() {
303   String paraValue="\n";
304   SimpleAttributeSet para_attr = new SimpleAttributeSet();
305   para_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntText);
306   StyleConstants.setFontSize(para_attr, 20);  
307   return new GenDiapoDocument.ElementSpec(para_attr, 
308             GenDiapoDocument.ElementSpec.ContentType, 
309             paraValue.toCharArray(),
310             0,
311             paraValue.length());
312     }
313 
314     /**
315      * Ajoute un element (non editable) dans le cas le noeud ne comporte pas d'attribut ou pcdata visible
316      * @param change Vecteur contenant les ElementSpec du document a créer
317      * @param node   Noeud a traiter
318      */
319     static void parseGlobalElementTree(Vector change, MerlotDOMNode node) {
320   if (node instanceof MerlotDOMElement) {
321       MerlotDOMEditor editor = node.getEditor();
322       if (editor instanceof GenDiapoEditor) {
323     GenDiapoEditor genDiapoEditor = (GenDiapoEditor) editor;
324     // Ajout le tag global uniquement si l'element est visible par l'utilisateur
325     if (!genDiapoEditor.suppressTag(node.getParentNode(), node.getNodeName())) {    
326         
327         SimpleAttributeSet attr_attr = new SimpleAttributeSet();
328         attr_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntDummy);
329         change.add(new GenDiapoDocument.ElementSpec(attr_attr, GenDiapoDocument.ElementSpec.StartTagType));
330 
331         SimpleAttributeSet para_attr = new SimpleAttributeSet();
332         para_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntParagraph);
333         change.add(new GenDiapoDocument.ElementSpec(para_attr, GenDiapoDocument.ElementSpec.StartTagType));
334 
335         change.add(voidTextElementSpec());  
336 
337         change.add(EndElementSpec);
338         change.add(EndElementSpec);
339     }
340       }
341   }
342     }
343         
344     /**
345      * Traitement d'un noeud de Merlot
346      * @param change Vecteur contenant les ElementSpec du document a créer
347      * @param node   MerlotDOMNode a ajouter au document sous forme d'ElementSpec
348      */
349     public static void parseMerlotNodeTree(Vector change, MerlotDOMNode node) {
350   String str;  
351   
352   // Lecture des fils
353   MerlotDOMNode childs[] = node.getChildNodes();
354 
355   // creer une liste des fils sans les noeuds invisible
356   Vector realChildsV = new Vector();
357   for(int i=0; i<childs.length; i++) {
358       if (childs[i] instanceof MerlotDOMText) {
359     if (((MerlotDOMText) childs[i]).isVisible()) {
360         realChildsV.add(childs[i]);
361     } 
362       } else {
363     realChildsV.add(childs[i]);
364       }
365   }
366   MerlotDOMNode[] realChilds = (MerlotDOMNode[]) realChildsV.toArray(new MerlotDOMNode[realChildsV.size()]);
367       
368   // PCData authorise ?
369   boolean pcDataAllowed = pcDataAllowed(node);
370 
371   // eventual empty pcdata as first child
372   if (pcDataAllowed) {
373             boolean addNewOne = false;
374       if (realChilds.length>0) {
375     if (!(realChilds[0] instanceof MerlotDOMText)) {
376                     addNewOne = true;
377     }
378       } else if (realChilds.length == 0) {
379                 addNewOne = true;
380       }
381             if (addNewOne) {               
382                 MerlotDOMNode firstChild = node.getFirstChild();
383                 MerlotDOMText textNode;
384                 if (firstChild == null) {
385                     textNode = (MerlotDOMText) node.newChild(DTDConstants.PCDATA_KEY);
386                 } else {
387                     textNode = (MerlotDOMText) firstChild.newSiblingBefore(DTDConstants.PCDATA_KEY);
388                 }                               
389                 parsePCDataTree(change, textNode);
390                 // addPCDataTree(change, GenDiapoDocument.ATTRIBUT_MERLOTTEXT_FIRST);                
391             }
392   }
393 
394   // add childs
395   for (int i=0; i<realChilds.length; i++) {
396       MerlotDOMNode child = realChilds[i];
397       if (child instanceof MerlotDOMElement) {
398     parseMerlotNode(change, child);
399       } else if (child instanceof MerlotDOMText) {
400     parsePCDataTree(change, (MerlotDOMText) child);
401       }
402   }
403   
404   // eventual empty pcdata as last child
405   if (pcDataAllowed) {
406       if (realChilds.length>0) {
407     if (!(realChilds[realChilds.length-1] instanceof MerlotDOMText)) {                    
408                     // Add a new node at the end
409                     MerlotDOMText textNode = (MerlotDOMText) node.newChild(DTDConstants.PCDATA_KEY);
410                     parsePCDataTree(change, textNode);        
411     }
412       }
413   }
414   
415     }
416     
417     /*
418      * Gestion du style
419      */
420 
421 
422     static boolean inParagraph(Vector change) {  
423   GenDiapoDocument.ElementSpec es = (GenDiapoDocument.ElementSpec) change.lastElement();
424   boolean retval = (es.getType() == GenDiapoDocument.ElementSpec.ContentType);
425   if (!retval) {
426       if (es.getType() == GenDiapoDocument.ElementSpec.StartTagType) {
427     AttributeSet attr = es.getAttributes();
428     Object o = attr.getAttribute(GenDiapoDocument.ATTRIBUT_TYPE);
429     if (o instanceof Integer) {
430         int type = ((Integer) o).intValue();
431         retval = (type == GenDiapoDocument.ParagraphCSS);
432     }
433       }
434   }
435   return retval;
436     }
437 
438     static void pushParagraph(Vector change, MerlotDOMNode root, MerlotDOMNode node, StyleSheet style) {
439   // Paragraph
440   Style paraStyle = getStyle(style, root, root);
441   SimpleAttributeSet para_attr = new SimpleAttributeSet();      
442   para_attr= new SimpleAttributeSet();      
443   para_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntParagraphCSS);
444   para_attr.addAttributes(paraStyle);
445   change.add(new GenDiapoDocument.ElementSpec(para_attr, GenDiapoDocument.ElementSpec.StartTagType));  
446     }
447 
448     static void popParagraph(Vector change, MerlotDOMNode root, MerlotDOMNode node, StyleSheet style) {
449   change.add(EndElementSpec);
450     }
451 
452 
453     /*---------------------------------*/
454     static void test(String selector) {
455   Vector elements = new Vector();
456   try {
457       boolean done;
458       int dotIndex = 0;
459       int spaceIndex = 0;
460       int poundIndex = 0;
461       int lastIndex = 0;
462       int length = selector.length();
463       while (lastIndex < length) {
464     if (dotIndex == lastIndex) {
465         dotIndex = selector.indexOf('.', lastIndex);
466     }
467     if (poundIndex == lastIndex) {
468         poundIndex = selector.indexOf('#', lastIndex);
469     }
470     spaceIndex = selector.indexOf(' ', lastIndex);
471     if (spaceIndex == -1) {
472         spaceIndex = length;
473     }
474     if (dotIndex != -1 && poundIndex != -1 &&
475         dotIndex < spaceIndex && poundIndex < spaceIndex) {
476         if (poundIndex < dotIndex) {
477       // #.
478       if (lastIndex == poundIndex) {
479           elements.addElement("");
480       }
481       else {
482           elements.addElement(selector.substring(lastIndex,
483                   poundIndex));
484       }
485       if ((dotIndex + 1) < spaceIndex) {
486           elements.addElement(selector.substring
487             (dotIndex + 1, spaceIndex));
488       }
489       else {
490           elements.addElement(null);
491       }
492       if ((poundIndex + 1) == dotIndex) {
493           elements.addElement(null);
494       }
495       else {
496           elements.addElement(selector.substring
497             (poundIndex + 1, dotIndex));
498       }
499         }
500         else if(poundIndex < spaceIndex) {
501       // .#
502       if (lastIndex == dotIndex) {
503           elements.addElement("");
504       }
505       else {
506           elements.addElement(selector.substring(lastIndex,
507                   dotIndex));
508       }
509       if ((dotIndex + 1) < poundIndex) {
510           elements.addElement(selector.substring
511             (dotIndex + 1, poundIndex));
512       }
513       else {
514           elements.addElement(null);
515       }
516       if ((poundIndex + 1) == spaceIndex) {
517           elements.addElement(null);
518       }
519       else {
520           elements.addElement(selector.substring
521             (poundIndex + 1, spaceIndex));
522       }
523         }
524         dotIndex = poundIndex = spaceIndex + 1;
525     }
526     else if (dotIndex != -1 && dotIndex < spaceIndex) {
527         // .
528         if (dotIndex == lastIndex) {
529       elements.addElement("");
530         }
531         else {
532       elements.addElement(selector.substring(lastIndex,
533                      dotIndex));
534         }
535         if ((dotIndex + 1) == spaceIndex) {
536       elements.addElement(null);
537         }
538         else {
539       elements.addElement(selector.substring(dotIndex + 1,
540                      spaceIndex));
541         }
542         elements.addElement(null);
543         dotIndex = spaceIndex + 1;
544     }
545     else if (poundIndex != -1 && poundIndex < spaceIndex) {
546         // #
547         if (poundIndex == lastIndex) {
548       elements.addElement("");
549         }
550         else {
551       elements.addElement(selector.substring(lastIndex,
552                      poundIndex));
553         }
554         elements.addElement(null);
555         if ((poundIndex + 1) == spaceIndex) {
556       elements.addElement(null);
557         }
558         else {
559       elements.addElement(selector.substring(poundIndex + 1,
560                      spaceIndex));
561         }
562         poundIndex = spaceIndex + 1;
563     }
564     else {
565         // id
566         elements.addElement(selector.substring(lastIndex,
567                  spaceIndex));
568         elements.addElement(null);
569         elements.addElement(null);
570     }
571     lastIndex = spaceIndex + 1;
572       }
573 
574 
575       // Create the tag, id, and class arrays.
576       int total = elements.size();
577       int numTags = total / 3;
578       String[] tags = new String[numTags];
579       String[] ids = new String[numTags];
580       String[] classes = new String[numTags];
581       for (int index = 0, eIndex = total - 3; index < numTags;
582      index++, eIndex -= 3) {
583     tags[index] = (String)elements.elementAt(eIndex);
584     ids[index] = (String)elements.elementAt(eIndex + 1);
585     classes[index] = (String)elements.elementAt(eIndex + 2);
586       }
587 
588       // print
589       System.out.println("test ------<");
590       System.out.print("tags=");
591       for (int i=0; i<tags.length; i++) {
592     System.out.print("'"+tags[i]+"' ");
593       }
594       System.out.print("\nids=");
595       for (int i=0; i<tags.length; i++) {
596     System.out.print("'"+ids[i]+"' ");
597       }
598       System.out.print("\nclasses=");
599       for (int i=0; i<tags.length; i++) {
600     System.out.print("'"+classes[i]+"' ");
601       }
602       System.out.println("\ntest ------>");
603   } catch (Exception e) {
604       System.out.println(e.getMessage());
605   }
606     }
607 
608     /*---------------------------------*/
609 
610     static Style getStyleAttribute(StyleSheet style, MerlotDOMNode node, DTDAttribute nodeAttr) {
611   String str = node.getNodeName()+":"+nodeAttr.getName();
612   Style retval = style.getRule(str);
613   return retval;
614     }
615 
616     static Style getStyle(StyleSheet style, MerlotDOMNode root, MerlotDOMNode node) {
617   String str = "";
618   String glue = "";
619 
620   String rootName;
621   root = root.getParentNode();
622   if (root == null) {
623       rootName = "";
624   } else {
625       rootName = root.getNodeName();
626   }
627 
628   //str = "paragraph";
629   //glue = " ";
630 
631   while (node != null) {
632       if (node instanceof MerlotDOMElement) {
633     str = node.getNodeName() + glue + str;
634     glue = " ";
635       }
636       node = node.getParentNode();
637       if (node != null) {
638     if (node.getNodeName().equals(rootName)) {
639         node = null;
640     }      
641       }
642   }
643   Style retval = style.getRule(str);
644   
645   /*
646     test(str);
647     System.out.println("getStyle----------------------<");
648     System.out.println("name="+str);
649     System.out.println("isBold     : "+StyleConstants.isBold(retval));
650     System.out.println("isItalic   : "+StyleConstants.isItalic(retval));
651     System.out.println("isUnderline: "+StyleConstants.isUnderline(retval));
652     System.out.println("getStyle---------------------->");
653   */
654 
655   return retval;
656     }
657 
658     public static HashMap getNodeAttributes(MerlotDOMNode node) {
659   
660   HashMap attributes = new HashMap();
661 
662   Enumeration dtdAttributes = node.getDTDAttributes();
663   org.w3c.dom.Node xmlNode = node.getRealNode();
664   if (dtdAttributes != null) {
665       DTDAttribute nodeAttr;
666       SimpleAttributeSet attr_attr, text_attr, para_attr;
667       String attrValue, attrName;
668       
669       while (dtdAttributes.hasMoreElements()) {
670     nodeAttr = (DTDAttribute)dtdAttributes.nextElement();
671 
672     attrName = nodeAttr.getName();
673     
674     attrValue="";
675     if (xmlNode instanceof org.w3c.dom.Element) {
676         attrValue = ((org.w3c.dom.Element)xmlNode).getAttribute(nodeAttr.getName()); 
677     } 
678     
679     attributes.put(nodeAttr.getName(), attrValue);
680     
681       }
682   }
683   
684   return attributes;
685     }
686 
687     static String getPath(MerlotDOMNode node) {
688   String path = "";
689   while (node != null) {
690       path = node.getNodeName()+"/"+path;     
691       node = node.getParentNode();
692   }
693   path += GenDiapoDocument.ATTRIBUT_STYLEATTRIBUTES; 
694   return path;
695     }
696     
697     static SimpleAttributeSet getDocumentAttributes(MerlotDOMNode root, MerlotDOMNode node) {
698   SimpleAttributeSet attr = new SimpleAttributeSet();
699   root = root.getParentNode();       
700   while ( (node != null) && (node != root) )  {
701       attr.addAttribute(getPath(node), getNodeAttributes(node));
702       node = node.getParentNode();
703   }
704   return attr;
705     }
706 
707     public static AttributeSet getAttributesCSSLabel(MerlotDOMNode node, Style style) {
708   SimpleAttributeSet textAttr = new SimpleAttributeSet();      
709   textAttr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntTextCSS);
710   textAttr.addAttribute(GenDiapoDocument.ATTRIBUT_STYLENAME, style.getName());
711   textAttr.addAttributes(style);
712   // Ajout des attributes
713   
714   return textAttr;
715     }
716 
717     static void parsePCDataStyle(Vector change, MerlotDOMNode root, MerlotDOMNode node, StyleSheet style) {
718   // verifie s'il y a besoin d'un pushParagraph
719   if (!inParagraph(change)) {
720       pushParagraph(change, root, node, style);      
721   }
722 
723   // Text
724   String text = ((MerlotDOMText)node).getText();
725   
726   Style cssStyle = getStyle(style, root, node);
727   AttributeSet textAttr = getAttributesCSSLabel(node, cssStyle);
728 
729   ((SimpleAttributeSet) textAttr).addAttributes(getDocumentAttributes(root, node));
730 
731   change.add(new GenDiapoDocument.ElementSpec(textAttr, 
732                 GenDiapoDocument.ElementSpec.ContentType, 
733                 text.toCharArray(),
734                 0,
735                 text.length()));
736 
737   // s'il y a un retour a la ligne -> change de paragraphe
738   if (text.length() > 0) {
739       if (text.charAt(text.length()-1) == '\n') {
740     popParagraph(change, root, node, style);
741       }
742   }
743 
744     }
745 
746     static void parseEndNodeStyle(Vector change, MerlotDOMNode root, MerlotDOMNode node, StyleSheet style) {
747   // Text
748   String text = "\n";
749 
750   Style cssStyle = getStyle(style, root, node);
751   AttributeSet textAttr = getAttributesCSSLabel(node, cssStyle);  
752 
753   change.add(new GenDiapoDocument.ElementSpec(textAttr, 
754                 GenDiapoDocument.ElementSpec.ContentType, 
755                 text.toCharArray(),
756                 0,
757                 text.length()));
758     }
759 
760     static void parseMerlotNodeStyleInside(Vector change, MerlotDOMNode root, MerlotDOMNode node, StyleSheet style) {
761   // parse des enfants
762   MerlotDOMNode childs[] = node.getChildNodes();
763   for(int i=0; i<childs.length; i++) {
764       if (childs[i] instanceof MerlotDOMText) {
765     parsePCDataStyle(change, root, childs[i], style);  // isVisible ignore
766       } else {
767     parseMerlotNodeStyleInside(change, root, childs[i], style);
768       }
769   }  
770     }   
771         
772     public static void parseMerlotNodeStyle(Vector change, MerlotDOMNode node, StyleSheet style) {
773   // <pcdata>
774   SimpleAttributeSet attr_attr= new SimpleAttributeSet();      
775   attr_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntFragment);
776   change.add(new GenDiapoDocument.ElementSpec(attr_attr, GenDiapoDocument.ElementSpec.StartTagType));
777 
778   // 1er paragraphe
779   pushParagraph(change, node, node, style);
780   
781   // parse chaque noeud
782   parseMerlotNodeStyleInside(change, node, node, style);
783 
784   // ferme le dernier paragraph  
785   if (inParagraph(change)) {      
786       parseEndNodeStyle(change, node, node, style);
787       popParagraph(change, node, node, style);
788   }
789 
790   // </pcdata>
791   change.add(EndElementSpec);
792     }    
793 
794     static void parseMerlotNodeCustom(Vector change, MerlotDOMNode node, NodeControler nodeControler) {
795   nodeControler.parse(node, change);
796     }
797 
798     public static void parseMerlotNode(Vector change, MerlotDOMNode node) {
799   if (!( (node instanceof MerlotDOMElement) || (node instanceof MerlotDOMDocument) )) { 
800       // uniquement les tags de type element et le document
801       // Le reste ne sait pas etre traiter
802       return;
803   }
804 
805   // Traitement du noeud "node"
806   int editionType = GenDiapoEditor.EDITION_TREE;
807   org.w3c.dom.Node xmlNode = node.getRealNode();
808   MerlotDOMEditor editor = node.getEditor();
809   ViewFactory viewFactory = null;
810   StyleSheet style = null;
811   NodeControler nodeControler = null;
812         boolean addVoid = true;
813   if (editor instanceof GenDiapoEditor) {
814       viewFactory = ((GenDiapoEditor)editor).getViewFactory(node);
815       style = ((GenDiapoEditor)editor).getStyleSheet(node);
816       editionType = ((GenDiapoEditor)editor).editionType(node);
817       nodeControler = ((GenDiapoEditor)editor).getNodeControler(node);
818             addVoid = ((GenDiapoEditor)editor).addVoid(node);
819   }
820   
821   // Nom
822   SimpleAttributeSet node_attr = new SimpleAttributeSet();      
823   node_attr.addAttribute(GenDiapoDocument.ATTRIBUT_MERLOTNODE, node);
824   node_attr.addAttribute(GenDiapoDocument.ATTRIBUT_XMLNODE, xmlNode);
825   node_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, new java.lang.Integer(xmlNode.getNodeType()));
826   node_attr.addAttribute(GenDiapoDocument.EDITION_TYPE, new java.lang.Integer(editionType));
827   if (viewFactory != null) {
828       node_attr.addAttribute(GenDiapoDocument.VIEWFACTORY, viewFactory);
829   }
830   if (style != null) {
831       node_attr.addAttribute(GenDiapoDocument.STYLESHEET, style);
832   }
833   change.add(new GenDiapoDocument.ElementSpec(node_attr, GenDiapoDocument.ElementSpec.StartTagType));
834   
835   // Global Element
836         if (addVoid) {
837             parseGlobalElementTree(change, node);
838         }
839 
840   // Detection du type de node (tree ou style)
841   switch (editionType) {
842   case GenDiapoEditor.EDITION_TREE :
843       parseAttributes(change, node, style);
844       parseMerlotNodeTree(change, node);
845       break;
846   case GenDiapoEditor.EDITION_STYLE :
847       parseAttributes(change, node, style);
848       parseMerlotNodeStyle(change, node, style);
849       break;
850   case GenDiapoEditor.EDITION_CUSTOM :
851       parseMerlotNodeCustom(change, node, nodeControler);
852       break;
853   }
854 
855   // EndTag
856   change.add(EndElementSpec);  
857     }
858     
859     private static void deleteLastElement(GenDiapoDocument doc) {
860   int length = doc.getLength();
861   Element[] none = new Element[0];
862 
863   // Supression de la feuille
864   Element elem = doc.getParagraphElement(length);
865   int nb = elem.getElementCount();
866   
867   ((GenDiapoDocument.NodeElement)elem).replace(nb-1,1,none);
868   
869   // Supression du noeud
870   elem = ((GenDiapoDocument.NodeElement) elem).getParentElement();
871   nb = elem.getElementCount();
872   ((GenDiapoDocument.NodeElement)elem).replace(nb-1,1,none);
873     }
874     
875     public static GenDiapoDocument create(MerlotDOMDocument merlotDocument) {
876   // Creation d'un vecteur d'ElementSpec a partir de merlotDocument
877   Vector all = new Vector();
878   parseMerlotNode(all, merlotDocument);
879   
880   // Conversion en Array
881   GenDiapoDocument.ElementSpec es[] = new GenDiapoDocument.ElementSpec[all.size()];
882   es = (GenDiapoDocument.ElementSpec[]) all.toArray(es);
883         all = null;
884       
885   // Creation du document
886   GenDiapoDocument document = new GenDiapoDocument(es);
887 
888   // Supprime le ending element si le document n'est pas vide
889   if (document.getLength() > 0) {
890       deleteLastElement(document);
891   }
892   
893   return document;  
894     }
895 
896     // 
897     public static GenDiapoDocument insertNode(GenDiapoDocument document, MerlotDOMNode node) 
898   throws javax.swing.text.BadLocationException {
899   // get previous visual element (logical previous or father)
900   boolean previousIsFather = false;
901   MerlotDOMNode previous = node.getPreviousSibling();
902 
903   while (previous==null?false:((previous instanceof MerlotDOMText)?(!((MerlotDOMText) previous).isVisible()):false)) {
904       previous = previous.getPreviousSibling();
905   }
906   
907   if (previous == null) {
908       previous = node.getParentNode();
909       previousIsFather = true;      
910   }
911   
912   // get element associate with node
913   javax.swing.text.Element nodeElement = document.findElementWithProperty(GenDiapoDocument.ATTRIBUT_MERLOTNODE, previous);
914   int offset = nodeElement.getEndOffset();
915   Vector elementspec = new Vector();
916   
917   // up while not in node       
918         javax.swing.text.Element e = nodeElement;
919   //   skip one level is previousIsFather to be inside father (and not a sibling)
920   if (previousIsFather) {
921       int index = e.getElementIndex(offset);
922       e = e.getElement(index);
923   }
924   while (!e.isLeaf()) {
925       int index = e.getElementIndex(offset);
926       e = e.getElement(index);
927       elementspec.add(EndElementSpec);      
928   }
929 
930   // parse new node
931   GenDiapoDocumentFactory.parseMerlotNode(elementspec, node);
932   GenDiapoDocument.ElementSpec es[] = new GenDiapoDocument.ElementSpec[elementspec.size()];
933   es = (GenDiapoDocument.ElementSpec[]) elementspec.toArray(es);
934 
935   // insert new node at the end
936   document.insert(offset, es);
937   return document;
938     }
939 
940     public static GenDiapoDocument deleteNode(GenDiapoDocument document, MerlotDOMNode node) 
941   throws javax.swing.text.BadLocationException {
942   javax.swing.text.Element nodeElement = document.findElementWithProperty(GenDiapoDocument.ATTRIBUT_MERLOTNODE, node);
943   int offsetStart = nodeElement.getStartOffset();
944   int offsetEnd   = nodeElement.getEndOffset();
945   int length      = offsetEnd-offsetStart;
946   document.removeUncheck(offsetStart, length);
947   return document;
948     } 
949 
950 }