KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > schema2beans > DDRegistryParser


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.schema2beans;
21
22 import java.util.*;
23
24
25 /**
26  * The DDRegistryParser is a parser/Iterator on a set of graphs, as
27  * registered in the schema2beans registry (DDRegistry).
28  *
29  * DDParser is a parser/Iterator on a single schema2beans graph, using
30  * a schema2beans path description to define what should be parsed.
31  * DDRegistryParser extend the functiionality of DDParser by providing
32  * a parsing mechanism on a set of graphs (instead of a single one) and
33  * by adding more syntax to the DDParser schema2beans path syntax.
34  *
35  * Where DDParser defined a DDLocation to define a location reference in
36  * the parsed graph, DDRegistryParser defines a DDCursor. The DDCursor
37  * defines a location on a set of graphs (a DDCursor might have a parent
38  * root defined in another graph).
39  *
40  * The DDRegistryParser instances are created by the DDRegistry.
41  */

42 public class DDRegistryParser implements Iterator {
43     
44     static final String JavaDoc CURRENT_CURSOR = "."; // NOI18N
45

46     /**
47      * Analyze and resolve the vriable references specified in the path
48      */

49     static public class PathResolver {
50     
51     static final char VARBEGIN = '{';
52     static final char VAREND = '}';
53     static final char VALUE = '#';
54     
55     // Current module (display/non unique) name
56
static final String JavaDoc VAR_MODNAME = "mname"; // NOI18N
57

58     // Current module unique name
59
static final String JavaDoc VAR_UNAME = "uname"; // NOI18N
60

61     // Parent schema2beans type of the specified type {#ptype.EnvEntry}
62
// would be either Session or Entity.
63
static final String JavaDoc VAR_PTYPE = "ptype"; // NOI18N
64

65     static final String JavaDoc VAR_TYPE = "type"; // NOI18N
66

67     
68     String JavaDoc result = null;
69
70     //
71
public PathResolver() {
72     }
73     
74     //
75
public PathResolver(DDCursor cursor, String JavaDoc path) {
76         this.result = this.resolvePath(cursor, path);
77     }
78     
79     
80     static boolean needResolving(String JavaDoc path) {
81         if (path != null)
82         return (path.indexOf(VARBEGIN) != -1);
83         else
84         return false;
85     }
86     
87     /**
88      * This resolve all the variables referenced in the path string
89      * using the knowledge of its current location. A variable is
90      * defined with braces {}, and might use any of the values:
91      *
92      * #mname, #uname, #ptype, #type
93      *
94      * or any reference to a property of the current graph:
95      *
96      * {NodeName} // no # in this case
97      *
98      */

99     String JavaDoc resolvePath(DDCursor cur, String JavaDoc path) {
100         if(path.indexOf(VARBEGIN) != -1) {
101         int i1 = path.indexOf(VARBEGIN);
102         int i2 = path.indexOf(VAREND);
103         String JavaDoc v =
104         (String JavaDoc)this.resolvePathVar(cur, path.substring(i1+1, i2));
105         return path.substring(0, i1).trim() + v +
106         this.resolvePath(cur, path.substring(i2+1));
107         }
108         return path.trim();
109     }
110     
111     Object JavaDoc resolvePathVar(DDCursor cur, String JavaDoc path) {
112         //path = path.trim();
113

114         if (path.indexOf(VARBEGIN) != -1 || path.indexOf(VAREND) != -1) {
115         throw new IllegalArgumentException JavaDoc(Common.getMessage(
116         "CannotNestDeclaration_msg"));
117         }
118         
119         if (path.indexOf('#') == 0 ) {
120         path = path.substring(1, path.length());
121         
122         String JavaDoc remSuffix = null;
123         int idx = path.indexOf('-');
124         if (idx != -1) {
125             // Might have to remove a suffix from the value
126
remSuffix = path.substring(idx+1);
127             path = path.substring(0, idx);
128         }
129         
130         if (path.startsWith(VAR_MODNAME)) {
131             int in = path.indexOf(':');
132             if (in != -1) {
133             String JavaDoc name = path.substring(in+1);
134             path = this.getDDNameValue(cur, name).toString();;
135             path = cur.getRegistry().getName(path);
136             } else {
137             path = cur.getRegistry().getName(cur);
138             }
139         } else
140             if (path.startsWith(VAR_UNAME)) {
141             path = cur.getRegistry().getID(cur);
142             } else
143             if (path.startsWith(VAR_PTYPE)) {
144                 int i = path.indexOf('.');
145                 if (i != -1) {
146                 String JavaDoc t = path.substring(i+1);
147                 DDCursor pc = cur;
148                 BaseBean bean;
149                 do {
150                     bean = this.getBean(pc.getRoot(), t);
151                     if (bean == null) {
152                     pc = pc.getParent();
153                     }
154                 } while(bean == null && pc != null);
155                 
156                 if (bean != null) {
157                     path = bean.parent().name();
158                 }
159                 }
160             } else
161                 if (path.startsWith(VAR_TYPE)) {
162                 path = cur.getRoot().name();
163                 }
164         
165         if (remSuffix != null) {
166             if (path.endsWith(remSuffix)) {
167             path = path.substring(0, path.length() -
168             remSuffix.length());
169             }
170         }
171         
172         return path;
173         } else {
174         return this.getDDNameValue(cur, path);
175         }
176     }
177     
178     private Object JavaDoc getDDNameValue(DDCursor pc, String JavaDoc path) {
179         Object JavaDoc val = null;
180         
181         // Look for the value in the DDCursors and current graph
182
// hierarchy (look first in the graph then in other DDCursors)
183
do {
184         val = this.getValue(pc.getRoot(), path);
185         if (val == null) {
186             pc = pc.getParent();
187         }
188         } while(val == null && pc != null);
189         return val;
190     }
191     
192     BaseBean getBean(BaseBean root, String JavaDoc name) {
193         while (root != null && !root.isRoot()) {
194         if (root.hasName(name))
195             return root;
196         root = root.parent();
197         }
198         return null;
199     }
200     
201     String JavaDoc getValue(BaseBean root, String JavaDoc name) {
202         String JavaDoc val = null;
203         if (root != null) {
204         do {
205             try {
206             val = (String JavaDoc)root.getValue(name);
207             break;
208             } catch(Exception JavaDoc e) {
209             // Unknown property name - ignore it
210
}
211             root = root.parent();
212         } while (root != null && !root.isRoot());
213         }
214         return val;
215     }
216     
217     public String JavaDoc toString() {
218         return this.result;
219     }
220     }
221
222     /**
223      * DDCursor is a location reference in one of the DDRegistry graphs.
224      * Note that DDCursor can be created in two different ways: from a schema2beans
225      * path or from a schema2beans node (BaseBean).
226      */

227     static public class DDCursor {
228     DDCursor parent;
229     BaseBean root;
230     DDRegistry registry;
231     
232     public DDCursor(DDCursor parent, String JavaDoc path) {
233         this(parent, (BaseBean)null);
234         this.resolve(path);
235     }
236     
237     public DDCursor(DDCursor parent, BaseBean root) {
238         this.parent = parent;
239         this.root = root;
240         if (this.registry == null && parent != null)
241         this.registry = parent.registry;
242     }
243     
244     public DDCursor(DDRegistry reg, String JavaDoc path) {
245         this.parent = null;
246         this.root = null;
247         this.registry = reg;
248         this.resolve(path);
249     }
250     
251     public DDCursor(DDRegistry reg, BaseBean root) {
252         this.parent = null;
253         this.root = root;
254         this.registry = reg;
255     }
256     
257     public DDRegistry getRegistry() {
258         return this.registry;
259     }
260     
261     public BaseBean getRoot() {
262         return this.root;
263     }
264     
265     public DDCursor getParent() {
266         return this.parent;
267     }
268     
269     public Object JavaDoc getValue(String JavaDoc name) {
270         if (root != null)
271         return this.root.getValue(name);
272         else
273         return null;
274     }
275     
276     void resolve(String JavaDoc path) {
277         
278         if (path == null) return;
279         path = path.trim();
280         if (path.equals("")) return; // NOI18N
281

282         if (path.startsWith("[") && path.endsWith("]")) { // NOI18N
283
this.resolveGraph(path.substring(1,path.length()-1));
284         return;
285         }
286         
287         // Find the proper root
288
if (this.parent == null) {
289         throw new IllegalStateException JavaDoc(Common.getMessage(
290         "CantResolveBecauseMissingParent_msg", path));
291         }
292         
293         // Resolve any embeded {} variables
294
if (PathResolver.needResolving(path))
295         path = (new PathResolver(this.parent, path)).toString();
296         
297         BaseBean root = this.parent.getRoot();
298         
299         if (root != null) {
300         DDParser p = new DDParser(root, path);
301         if (p.hasNext()) {
302             Object JavaDoc o = p.next();
303             if (o instanceof BaseBean) {
304             this.root = (BaseBean)o;
305             } else {
306             throw new IllegalStateException JavaDoc(
307             Common.getMessage(
308             "ParsingPathDoesntResolveToGraphNodeElement_msg",
309             path, o.getClass().getName(), o.toString()));
310             }
311         } else {
312             throw new IllegalStateException JavaDoc(Common.getMessage(
313             "NoElementFoundPath_msg", path));
314         }
315         } else {
316         throw new IllegalStateException JavaDoc(Common.getMessage(
317         "NoRootFoundForPath_msg", path));
318         }
319     }
320     
321     void resolveGraph(String JavaDoc path) {
322         String JavaDoc pathRoot = null;
323         
324         if (PathResolver.needResolving(path))
325         path = (new PathResolver(this.parent, path)).toString();
326         
327         int idx = path.indexOf(':');
328         if (idx != -1) {
329         pathRoot = path.substring(idx+1);
330         path = path.substring(0, idx);
331         }
332         
333         BaseBean[] beans = this.registry.getRoots(path);
334
335         if (beans.length > 0) {
336         this.root = beans[0];
337         if (pathRoot != null) {
338             DDCursor cur = new DDRegistryParser.DDCursor(this,
339                                  pathRoot);
340             this.root = cur.getRoot();
341         }
342         }
343     }
344     
345     public String JavaDoc toString() {
346         String JavaDoc p, r;
347         
348         if (this.parent != null)
349         p = this.parent.toString();
350         else
351         p = "-"; // NOI18N
352

353         if (this.root != null)
354         r = root.name();
355         else
356         r = "-"; // NOI18N
357
return "Parent:"+p+" Root:"+r; // NOI18N
358
}
359     
360     public String JavaDoc dump() {
361         if (this.root != null)
362         return this.root.dumpBeanNode();
363         else
364         return "<null graph>"; // NOI18N
365
}
366     }
367     
368     
369     DDRegistry registry;
370     
371     //
372
// The root of the parsing can be defined by:
373
// - a parent parser
374
// - a parent cursor
375
// - a graph reference in the scope definition: [graph_name]
376
//
377
DDRegistryParser parentParser = null;
378     DDCursor parentCursor = null;
379     DDRegistryParser parserRoot = null;
380     
381     ParserSet parser = null;
382     
383     public DDRegistryParser(DDRegistry reg, DDRegistryParser rp,
384                 String JavaDoc path) {
385     this.registry = reg;
386     this.initialize(path, rp, null);
387     }
388     
389     public DDRegistryParser(DDRegistry reg, DDCursor cursor,
390                 String JavaDoc path) {
391     this.registry = reg;
392     this.initialize(path, null, cursor);
393     }
394     
395     public DDRegistryParser(DDRegistry reg, String JavaDoc path) {
396     this.registry = reg;
397     this.initialize(path, null, null);
398     }
399     
400     public DDRegistry getRegistry() {
401     return this.registry;
402     }
403     
404     /**
405      * Initialize the parser. Either the parser or cursor is set, not both.
406      */

407     void initialize(String JavaDoc path, DDRegistryParser regParser, DDCursor cursor) {
408     String JavaDoc graphName = null;
409     String JavaDoc subpath = null;
410     String JavaDoc parsingPath = null;
411     
412     //
413
// A scope ([NAME]) refers to a graph or set of graphs in the
414
// registry. In such case, the scope is the root of the parser
415
// (and parserRoot = null) since we'll get our root beans from the
416
// scope and not from the parent parser or cursor
417
// (if any specified).
418
//
419
//path = path.trim();
420

421     DDCursor cur = cursor;
422     if (cur == null && regParser != null)
423         cur = regParser.getCursor();
424     
425     if (path.startsWith("[")) { // NOI18N
426
int idx = path.indexOf(']');
427         graphName = path.substring(1, idx);
428         
429         if (path.length() > idx+1)
430         path = path.substring(idx+1, path.length());
431         else
432         path = "."; // NOI18N
433

434         idx = graphName.indexOf(':');
435         if (idx != -1) {
436         subpath = graphName.substring(idx+1, graphName.length()-1);
437         graphName = graphName.substring(0, idx);
438
439         if (PathResolver.needResolving(subpath))
440             subpath = (new PathResolver(cur, subpath)).toString();
441         }
442         
443         if (PathResolver.needResolving(graphName))
444         graphName = (new PathResolver(cur, graphName)).toString();
445         
446         if (graphName.equals(CURRENT_CURSOR) && cursor != null)
447         graphName = null;
448     }
449     
450     if (PathResolver.needResolving(path))
451         parsingPath = (new PathResolver(cur, path)).toString();
452     else
453         parsingPath = path;
454     
455     
456     if (graphName == null && regParser == null && cursor == null) {
457         throw new IllegalStateException JavaDoc(Common.getMessage(
458         "CantFindRootForParser_msg"));
459     }
460     
461     //
462
// We know that we have a parent root - if the graphName
463
// is specified, then we get the root from the registry
464
//
465
if (graphName != null) {
466         
467         //
468
// The parser is initialized with an absolute graph
469
// name reference, such as [ejbmodule]
470
// That means that we get 1-n BaseBean(s) from the registry
471
// that we use as the root of the parsing.
472
//
473
BaseBean[] beans = this.registry.getRoots(graphName);
474         this.parser = new ParserSet(beans, null, parsingPath);
475         this.parser.setRoot();
476     } else if (regParser != null) {
477         
478         //
479
// The parser is initialized from another parser. That means
480
// that the current position of the other parser is used
481
// as the root of this new parser. However, we need to consider
482
// two cases: 1. the other parser has defined a set of roots
483
// (previous case when the parser is initialized with []),
484
// 2. the other parser has only one root.
485
// If the other parser was initialized as a set of roots,
486
// we need to get all of them to initialize this parser (or
487
// we'll miss the 2-n graphs in the parsing).
488
//
489
if (regParser.isRoot() && regParser.getRoots().length > 1) {
490         BaseBean[] beans = regParser.getRoots();
491         
492         // If the other parser has a parsingPath, we need to
493
// get the beans using this parsingPath
494
if (regParser.hasParsingPath()) {
495             String JavaDoc pp = regParser.getParsingPath();
496             ArrayList tmpArr = new ArrayList();
497             
498             for (int i=0; i<beans.length; i++) {
499             DDParser tmp = new DDParser(beans[i], pp);
500             if (tmp.hasNext())
501                 tmpArr.add(tmp.next());
502             }
503             BaseBean[] newBeans = new BaseBean[tmpArr.size()];
504             beans = (BaseBean[])tmpArr.toArray(newBeans);
505         }
506         
507         this.parser = new ParserSet(beans, null, parsingPath);
508         } else {
509         while (regParser.current() == null && regParser.hasNext())
510             regParser.next();
511         
512         this.parser = new ParserSet((BaseBean)regParser.current(), cur,
513                         parsingPath);
514         
515         }
516         
517     } else if (cursor != null) {
518         //
519
// The parser is initialized from a DDCursor position.
520
//
521
this.parser = new ParserSet(cursor.getRoot(), cur, parsingPath);
522     } else {
523         throw new IllegalStateException JavaDoc( Common.getMessage(
524         "NoParentSpecified_msg"));
525     }
526     }
527     
528     
529     boolean isRoot() {
530     return this.parser.isRoot();
531     }
532     
533     boolean hasParsingPath() {
534     return this.parser.hasParsingPath();
535     }
536     
537     String JavaDoc getParsingPath() {
538     return this.parser.getParsingPath();
539     }
540     
541     BaseBean[] getRoots() {
542     return this.parser.getRoots();
543     }
544     
545     // Reset the current ParsetSet to use the next available root from the
546
// parent.
547
public Object JavaDoc next() {
548     return this.parser.next();
549     }
550     
551     public boolean hasNext() {
552     return this.parser.hasNext();
553     }
554     
555     public DDCursor getCursor() {
556     Object JavaDoc o = this.current();
557     
558     if (o instanceof BaseBean) {
559         BaseBean b = (BaseBean)o;
560         if (b == null && this.hasNext())
561         b = (BaseBean)this.next();
562         if (b != null)
563         return new DDCursor(this.registry, b);
564     } else {
565         // Return our parent cursor or build a new one
566
DDCursor cur = this.parser.getParentCursor();
567         if (cur == null) {
568         BaseBean[] beans = this.parser.getRoots();
569         cur = new DDCursor(this.registry, beans[0]);
570         }
571         return cur;
572     }
573     return null;
574     }
575     
576     public DDParser.DDLocation getLocation() {
577     return this.parser.getLocation();
578     }
579     
580     public Object JavaDoc current() {
581     return this.parser.current();
582     }
583     
584     public void remove() {
585     throw new UnsupportedOperationException JavaDoc();
586     }
587     
588     public Object JavaDoc getValue(String JavaDoc ddName) {
589     BaseBean b = (BaseBean)this.current();
590     if (b == null && this.hasNext())
591         b = (BaseBean)this.next();
592     
593     if (b != null) {
594         // This will seach for the ddName element in the current
595
// graph and will also search in the ParentCursor graph
596
// if the element is not found
597
DDCursor cur = new DDCursor(this.parser.getParentCursor(), b);
598         PathResolver p = new PathResolver();
599         Object JavaDoc obj = p.resolvePathVar(cur, ddName);
600         return obj;
601     }
602     
603     return null;
604     }
605     
606     
607     /**
608      * ParserSet handle the parsing of a set of graph through the usage
609      * of DDParser. DDRegistryParser delegates the multi-graph parsing to
610      * this inner class.
611      */

612     class ParserSet {
613     private BaseBean[] roots;
614     private int cur;
615     private String JavaDoc parsingPath;
616     private DDParser curParser;
617     private boolean isRoot;
618     private DDCursor parentCursor;
619     
620     ParserSet(BaseBean[] roots, DDCursor cur, String JavaDoc path) {
621         if (roots != null && roots.length > 0 && roots[0] != null) {
622         this.cur = 0;
623         this.isRoot = false;
624         this.roots = roots;
625         this.parsingPath = path;
626         this.parentCursor = cur;
627         this.adjustPathRoot();
628         this.newParser();
629         } else {
630         throw new IllegalArgumentException JavaDoc(Common.getMessage(
631         "NoRootSpecified_msg", path));
632         }
633     }
634     
635     ParserSet(BaseBean root, DDCursor cur, String JavaDoc path) {
636         this(new BaseBean[] {root}, cur, path);
637     }
638     
639     void adjustPathRoot() {
640         if (this.parsingPath.startsWith("../")) { // NOI18N
641
int i = this.parsingPath.lastIndexOf("../"); // NOI18N
642
int n = i/3;
643         do {
644             for (int j=0; j<this.roots.length; j++) {
645             if (this.roots[j].isRoot())
646                 throw new Schema2BeansRuntimeException(Common.getMessage(
647                 "CantAccessBaseBeanNode_msg", this.parsingPath));
648             this.roots[j] = this.roots[j].parent();
649             }
650         } while(n-- > 0);
651         this.parsingPath = this.parsingPath.substring(i+3);
652         }
653     }
654     
655     BaseBean[] getRoots() {
656         return this.roots;
657     }
658     
659     DDCursor getParentCursor() {
660         return this.parentCursor;
661     }
662     
663     void setRoot() {
664         this.isRoot = true;
665     }
666     
667     boolean isRoot() {
668         return this.isRoot;
669     }
670     
671     boolean hasParsingPath() {
672         if (this.parsingPath != null)
673         return !this.parsingPath.equals("."); // NOI18N
674
else
675         return false;
676     }
677     
678     String JavaDoc getParsingPath() {
679         return this.parsingPath;
680     }
681     
682     private boolean newParser() {
683         if (this.cur < this.roots.length) {
684         try {
685             this.curParser =
686             new DDParser(this.roots[this.cur++], this.parsingPath);
687             return true;
688         } catch(NoSuchElementException e) {
689             // If the element is not found, try with our parent root,
690
// this might be a linked graph.
691
if(this.parentCursor != null) {
692             this.cur = 0;
693             this.roots =
694                 new BaseBean[] {this.parentCursor.getRoot()};
695             this.parentCursor = this.parentCursor.getParent();
696             return this.newParser();
697             }
698             else
699             throw e;
700         }
701         }
702         return false;
703     }
704     
705     //
706
boolean hasNext() {
707         boolean more = this.curParser.hasNext();
708         
709         while (!more && this.newParser())
710         more = this.curParser.hasNext();
711         
712         return more;
713     }
714     
715     DDParser.DDLocation getLocation() {
716         return this.curParser.getLocation();
717     }
718     
719     // Return what the parser has currently
720
Object JavaDoc current() {
721         return this.curParser.current();
722     }
723     
724     // Get the next element available from our set of parsers
725
Object JavaDoc next() {
726         if (this.hasNext()) {
727         return this.curParser.next();
728         } else {
729         throw new NoSuchElementException();
730         }
731     }
732     }
733 }
734
Popular Tags