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

Quick Search    Search Deep

Source code: org/merlotxml/merlot/GenericDOMEditor.java


1   /*
2   ====================================================================
3   Copyright (c) 1999-2000 ChannelPoint, Inc..  All rights reserved.
4   ====================================================================
5   
6   Redistribution and use in source and binary forms, with or without 
7   modification, are permitted provided that the following conditions 
8   are met:
9   
10  1. Redistribution of source code must retain the above copyright 
11  notice, this list of conditions and the following disclaimer. 
12  
13  2. Redistribution in binary form must reproduce the above copyright
14  notice, this list of conditions and the following disclaimer in the 
15  documentation and/or other materials provided with the distribution.
16  
17  3. All advertising materials mentioning features or use of this 
18  software must display the following acknowledgment:  "This product 
19  includes software developed by ChannelPoint, Inc. for use in the 
20  Merlot XML Editor (http://www.merlotxml.org/)."
21   
22  4. Any names trademarked by ChannelPoint, Inc. must not be used to 
23  endorse or promote products derived from this software without prior
24  written permission. For written permission, please contact
25  legal@channelpoint.com.
26  
27  5.  Products derived from this software may not be called "Merlot"
28  nor may "Merlot" appear in their names without prior written
29  permission of ChannelPoint, Inc.
30  
31  6. Redistribution of any form whatsoever must retain the following
32  acknowledgment:  "This product includes software developed by 
33  ChannelPoint, Inc. for use in the Merlot XML Editor 
34  (http://www.merlotxml.org/)."
35  
36  THIS SOFTWARE IS PROVIDED BY CHANNELPOINT, INC. "AS IS" AND ANY EXPRESSED OR 
37  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
38  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO 
39  EVENT SHALL CHANNELPOINT, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
40  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
41  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
42  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
43  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
44  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
45  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46   ====================================================================
47  
48  For more information on ChannelPoint, Inc. please see http://www.channelpoint.com.  
49  For information on the Merlot project, please see 
50  http://www.merlotxml.org
51  */
52  
53  package org.merlotxml.merlot;
54  
55  import java.io.*;
56  import java.awt.event.*;
57  import java.beans.*;
58  
59  import java.util.*;
60  import javax.swing.*;
61  import javax.swing.tree.*;
62  import java.awt.dnd.*;
63  import java.awt.datatransfer.*;
64  import java.io.*;
65  import org.w3c.dom.*;
66  import java.text.*;
67  import java.awt.Dimension;
68  import java.awt.Rectangle;
69  import matthew.awt.StrutLayout;
70  import org.merlotxml.util.xml.*;
71  
72  
73  /**
74   * Editor of nodes and such
75   *
76   */
77  
78  public class GenericDOMEditor implements MerlotDOMEditor, MerlotConstants
79  {
80    private static final String[] _editableTypes = {"ALL"};
81    
82    protected static Hashtable _invalidCharHash;
83    protected static Hashtable _manditoryFieldHash;
84  
85    public static final String SANITY_CHARS_PROP = "merlot.editor.generic.form.invalidchars";
86    public static final String SANITY_MANDITORY_PROP = "merlot.editor.generic.form.manditoryfields";
87    
88    
89  
90    public GenericDOMEditor () 
91    {
92      
93      
94    }
95      /**
96     * Returns a set of menu items for any special actions for 
97     * this particular editor
98     * that it wants in the popup menu. Standard stuff like cut, copy, paste
99     * is taken care of by other objects. If nothing needs added
100    */
101   public  JMenuItem[] getMenuItems(MerlotDOMNode node) 
102   {
103     return null;
104   }
105   
106   
107 
108   /**
109    * returns a panel for editing this type of component.
110    */
111   public JPanel getEditPanel(MerlotDOMNode node) 
112   {
113     JPanel p  = null;
114     
115     Node nd = node.getRealNode();
116      
117     int t = nd.getNodeType();
118     switch (t) {
119     case Node.TEXT_NODE:
120       p = new TextEditPanel((MerlotDOMText)node);
121       break;      
122     case Node.COMMENT_NODE:
123       p = new CommentEditPanel((MerlotDOMComment)node);
124       break;
125     case Node.PROCESSING_INSTRUCTION_NODE:
126       p = new ProcInstructionEditPanel((MerlotDOMProcessingInstruction)node);
127       break;
128     case Node.DOCUMENT_NODE:
129     case Node.DOCUMENT_TYPE_NODE:
130     case Node.DOCUMENT_FRAGMENT_NODE:
131     default:
132       p = new GenericDOMEditPanel(node);
133       break;      
134     }    
135     if (p != null)
136       installListener(p,node);
137 
138     return p;
139     
140   }
141   
142   public void savePanel(JPanel p) 
143     throws PropertyVetoException
144   {
145     if (p instanceof GenericDOMEditPanel) {
146       ((GenericDOMEditPanel)p).save();
147     }
148     else {
149       MerlotDebug.msg("Cannot save! Panel is not the right type.");
150     }
151     
152         
153   }
154   
155 
156   /**
157    * Returns the element types that this editor handles
158    */
159   public String[] getEditableTypes() 
160   {
161     return _editableTypes;
162   }
163   
164     
165   
166   /**
167    * returns true if this editor also edits it's children. If an editor
168    * says it handles it's children, then it must handle all it's children.<P>
169    */
170   public boolean editsChildren() 
171   {
172     return false;
173   }
174   
175   public void grabFocus(JPanel p) 
176   {
177     if (p instanceof GenericDOMEditPanel) {
178       ((GenericDOMEditPanel)p).grabFocus();
179     }
180   
181     
182   }
183   
184   /**
185    * Returns true if the component editor wants a particular node hidden
186    * from the user. If the editor wants to filter 
187    * what the user sees in their display, it should look at the
188    * given node, otherwise it should return false
189    */
190   public boolean suppressNode(MerlotDOMNode node) 
191   {
192     // check this node out to see if it's a #text or #comment 
193     // node, if so, hide it
194 
195     Node nd = node.getRealNode();
196     //  MerlotDebug.msg("filter nd = "+nd+" nodename = "+node.getNodeName());
197      
198     int t = nd.getNodeType();
199     switch (t) {
200     case Node.TEXT_NODE:
201       
202       if (nd instanceof CharacterData) {
203       
204       
205         //      MerlotDebug.msg("#text = "+s);
206         if (node instanceof MerlotDOMText && ((MerlotDOMText)node).isVisible()) {
207           return false;
208         }
209         String s = ((CharacterData)nd).getData();  
210         if (s != null) {
211           s = s.trim();
212           if ( s.equals("")) {
213             return true;
214           }
215           return false;
216         }
217       }
218       
219       return true;
220     case Node.COMMENT_NODE:
221       return false;
222     case Node.PROCESSING_INSTRUCTION_NODE:
223       return false;
224     case Node.DOCUMENT_NODE:
225       return true;
226     case Node.DOCUMENT_TYPE_NODE:
227       return true;
228     case Node.DOCUMENT_FRAGMENT_NODE:
229       return true;
230       
231     }
232     
233 
234     return false;
235   }
236   
237   public boolean suppressAddType(DTDElement el) 
238   {
239     return false;
240   }
241   
242   public void installListener(JPanel p, MerlotDOMNode node) 
243   {
244     if (p instanceof GenericDOMEditPanel) {
245       // install us as a listener
246       MerlotDebug.msg("installing listener for "+p);
247       
248       ((GenericDOMEditPanel)p).addVetoableChangeListener(new GenericSanityCheckListener());
249     }
250   }
251 
252   protected static final int START=0;
253   protected static final int NODENAME=1;
254   protected static final int ATTRNAME=2;
255   protected static final int EQUALS=3;
256   
257   protected static void parseInvalidCharsProp(String prop) 
258   {
259     int tokenstate = START;
260     Vector names = null;
261     Vector fields = null;
262     StringBuffer chars = null;
263     int err = 0;
264     if (prop == null) {
265       return;
266     }
267     
268     StringTokenizer tok = new StringTokenizer(prop,"=., ",true);
269     while (tok.hasMoreTokens()) {
270       String s = tok.nextToken();
271       if (s.length() > 0) {
272         char c = s.charAt(0);
273         switch (tokenstate) {
274         case START:
275           if (names != null && fields != null && chars != null) {
276             for (int i=0;i<names.size(); i++) {
277               for (int j=0;j<fields.size();j++) {
278                 String key = (String)names.elementAt(i) + "."+ (String)fields.elementAt(j);
279                 MerlotDebug.msg("GenericDOMEditor: putting key="+key+" chars='"+chars.toString()+"'");
280                 _invalidCharHash.put(key,chars.toString());
281               }
282             }
283             names = null;
284             fields = null;
285             chars = null;
286           }
287           if (tok.hasMoreTokens()) {
288             names = new Vector();
289             fields = new Vector();
290           }
291           
292           switch (c) {
293           case ',':
294           case '=':
295           case '.':
296           case ' ':
297             err++;
298             break;
299           default:
300             names.add(s);
301             tokenstate=NODENAME;
302             break;
303           }
304           break;
305         case NODENAME:
306           switch (c) {
307           case '=':
308             err++;
309             break;
310           case ',':
311             break;
312           case '.':
313             tokenstate=ATTRNAME;
314             break;
315           case ' ':
316             err++;
317             break;
318           default:
319             names.add(s);
320             break;
321           }
322           break;
323         case ATTRNAME:
324           switch (c) {
325           case '=':
326             chars = new StringBuffer();
327             tokenstate=EQUALS;
328             break;
329           case ',':
330             break;
331           case '.':
332           case ' ':
333             err++;
334             break;
335           default:
336             fields.add(s);
337             break;
338           }
339           break;
340         case EQUALS:
341           switch (c) {
342           case ' ':
343             tokenstate=START;
344             break;
345           default:
346             for (int i=0;i<s.length();i++) {
347               if (s.charAt(i) == '{') {
348                 int x = s.indexOf('}');
349                 if (x > 0) {
350                   String word = s.substring(i+1,x);
351                   if (word.equals("space")) {
352                     chars.append(' ');
353                   }
354                   i+=x;
355                   continue;
356                 }
357               }
358               chars.append(s.charAt(i));
359             }
360           }
361           break;
362         }
363       }
364     }
365     if (names != null && fields != null && chars != null) {
366       for (int i=0;i<names.size(); i++) {
367         for (int j=0;j<fields.size();j++) {
368           String key = (String)names.elementAt(i) + "." + (String)fields.elementAt(j);
369           MerlotDebug.msg("GenericDOMEditor: putting key="+key+" chars='"+chars.toString()+"'");
370           _invalidCharHash.put(key,chars.toString());
371         }
372       }
373       names = null;
374       fields = null;
375       chars = null;
376     }
377     
378   }
379   
380   protected static void parseManditoryFieldsProp(String prop) 
381   {
382     int tokenstate = START;
383     Vector names = null;
384     Vector fields = null;
385     int err = 0;
386     if (prop == null) {
387       return;
388     }
389     
390     StringTokenizer tok = new StringTokenizer(prop,"=, ",true);
391     while (tok.hasMoreTokens()) {
392       String s = tok.nextToken();
393       if (s.length() > 0) {
394         char c = s.charAt(0);
395         switch (tokenstate) {
396         case START:
397           if (names != null && fields != null) {
398             for (int i=0;i<names.size(); i++) {
399               for (int j=0;j<fields.size();j++) {
400                 String key = (String)names.elementAt(i) + "."+ (String)fields.elementAt(j);
401                 MerlotDebug.msg("GenericDOMEditor: putting manditory field key="+key);
402                 _manditoryFieldHash.put(key,"yes");
403               }
404             }
405             names = null;
406             fields = null;
407           }
408           if (tok.hasMoreTokens()) {
409             names = new Vector();
410             fields = new Vector();
411           }
412 switch (c) {
413           case ',':
414           case '=':
415           case '.':
416           case ' ':
417             err++;
418             break;
419           default:
420             names.add(s);
421             tokenstate=NODENAME;
422             break;
423           }
424           break;
425         case NODENAME:
426           switch (c) {
427           case '=':
428             tokenstate=EQUALS;
429             break;
430           case ',':
431             break;
432           case '.':
433             tokenstate=ATTRNAME;
434             break;
435           case ' ':
436             err++;
437             break;
438           default:
439             names.add(s);
440             break;
441           }
442           break;
443         case ATTRNAME:
444           switch (c) {
445           case '=':
446             tokenstate=EQUALS;
447             break;
448           case ',':
449             break;
450           case '.':
451           case ' ':
452             err++;
453             break;
454           default:
455             fields.add(s);
456             break;
457           }
458           break;
459         case EQUALS:
460           switch (c) {
461           case ' ':
462             tokenstate=START;
463             break;
464           case ',':
465             break;
466             
467           default:
468             fields.add(s);
469             break;
470           }
471           break;
472         }
473       }
474     }
475     if (names != null && fields != null) {
476       for (int i=0;i<names.size(); i++) {
477         for (int j=0;j<fields.size();j++) {
478           String key = (String)names.elementAt(i) + "."+ (String)fields.elementAt(j);
479           MerlotDebug.msg("GenericDOMEditor: putting manditory field key="+key);
480           _manditoryFieldHash.put(key,"yes");
481         }
482       }
483       names = null;
484       fields = null;
485     }
486     
487   }
488   
489   
490   protected static String getInvalidChars(MerlotDOMNode node, String fieldname) 
491   {
492     if (_invalidCharHash == null) {
493       _invalidCharHash = new Hashtable();
494       // load this up from the properties
495       String invalidcharsprop = XMLEditorSettings.getSharedInstance().getProperty(SANITY_CHARS_PROP);
496       parseInvalidCharsProp(invalidcharsprop);
497       
498       
499     }
500     if (node != null) {
501       String nodename = node.getNodeName();
502       return (String)_invalidCharHash.get(nodename+"."+fieldname);
503     }
504     return null;
505     
506   }
507   
508   protected static String getManditoryFields(MerlotDOMNode node, String fieldname) 
509   {
510     if (_manditoryFieldHash == null) {
511       _manditoryFieldHash = new Hashtable();
512       String manditoryfields = XMLEditorSettings.getSharedInstance().getProperty(SANITY_MANDITORY_PROP);
513       parseManditoryFieldsProp(manditoryfields);
514       
515     }
516     if (node != null) {
517       String nodename = node.getNodeName();
518       return (String)_manditoryFieldHash.get(nodename+"."+fieldname);
519     }
520     return null;
521             
522   }
523   
524 
525   public static class GenericSanityCheckListener implements VetoableChangeListener 
526   {
527     
528     public GenericSanityCheckListener() 
529     {
530     }
531     
532   
533     public void vetoableChange(PropertyChangeEvent evt) 
534       throws PropertyVetoException
535     {
536       //  System.out.println("vetoableChange");
537       
538       
539       // if the name has spaces or is blank, throw an exception
540       String t;
541       Object n = evt.getSource();
542       if (!(n instanceof MerlotDOMNode)) {
543         return;
544       }
545       MerlotDOMNode node = (MerlotDOMNode)n;
546       
547       String s = evt.getPropertyName();
548       Object o = evt.getNewValue();
549       if (o instanceof String) {
550         t = ((String)o).trim();
551       }
552       else {
553         t = null;
554       }
555       
556       String invalidchars = GenericDOMEditor.getInvalidChars(node,s);
557       if (t != null && invalidchars != null) {
558         
559         //  System.out.println("invalidchars = "+invalidchars);
560         // check the field value for invalid chars
561         for (int i=0;i<invalidchars.length();i++) {
562           char c = invalidchars.charAt(i);
563           if (t.indexOf(c) >= 0) {
564             String[] err = new String[3];
565             err[0] = node.getNodeName();
566             err[1] = s;
567             switch (c) {
568             case ' ':
569               err[2] = "space";
570               break;
571             case '.':
572               err[2] = "period";
573               break;
574             case ',':
575               err[2] = "comma";
576               break;
577             default:
578               err[2] = "'" + c + "'";
579               break;
580               
581             }
582             
583             throw new PropertyVetoException(MessageFormat.format(MerlotResource.getString(ERR,"illegal.value.attr.char"),err),evt);
584           }
585           
586         }
587       }
588       
589       String  manditory  = GenericDOMEditor.getManditoryFields(node,s);
590       if (manditory != null && manditory.equals("yes")) {
591         if (t == null || t.equals("")) {
592           String err[] = new String[2];
593           err[0] = node.getNodeName();
594           err[1] = s;
595           
596           throw new PropertyVetoException(MessageFormat.format(MerlotResource.getString(ERR,"manditory.field"),err),evt);
597         }
598       }
599     }
600   }
601   
602 
603     
604 
605 }