KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > importer > view > ViewParser


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.repo.importer.view;
18
19 import java.io.IOException JavaDoc;
20 import java.io.Reader JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Map JavaDoc;
23 import java.util.Stack JavaDoc;
24
25 import org.alfresco.repo.importer.Importer;
26 import org.alfresco.repo.importer.Parser;
27 import org.alfresco.service.cmr.dictionary.AspectDefinition;
28 import org.alfresco.service.cmr.dictionary.AssociationDefinition;
29 import org.alfresco.service.cmr.dictionary.DictionaryService;
30 import org.alfresco.service.cmr.dictionary.PropertyDefinition;
31 import org.alfresco.service.cmr.dictionary.TypeDefinition;
32 import org.alfresco.service.cmr.repository.NodeRef;
33 import org.alfresco.service.cmr.security.AccessStatus;
34 import org.alfresco.service.cmr.view.ImporterException;
35 import org.alfresco.service.namespace.NamespaceService;
36 import org.alfresco.service.namespace.QName;
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39 import org.xmlpull.v1.XmlPullParser;
40 import org.xmlpull.v1.XmlPullParserException;
41 import org.xmlpull.v1.XmlPullParserFactory;
42
43
44 /**
45  * Importer for parsing and importing nodes given the Repository View schema.
46  *
47  * @author David Caruana
48  */

49 public class ViewParser implements Parser
50 {
51     // Logger
52
private static final Log logger = LogFactory.getLog(ViewParser.class);
53     
54     // View schema elements and attributes
55
private static final String JavaDoc VIEW_CHILD_NAME_ATTR = "childName";
56     private static final String JavaDoc VIEW_DATATYPE_ATTR = "datatype";
57     private static final String JavaDoc VIEW_ISNULL_ATTR = "isNull";
58     private static final String JavaDoc VIEW_INHERIT_PERMISSIONS_ATTR = "inherit";
59     private static final String JavaDoc VIEW_ACCESS_STATUS_ATTR = "access";
60     private static final String JavaDoc VIEW_ID_ATTR = "id";
61     private static final String JavaDoc VIEW_IDREF_ATTR = "idref";
62     private static final String JavaDoc VIEW_PATHREF_ATTR = "pathref";
63     private static final String JavaDoc VIEW_NODEREF_ATTR = "noderef";
64     private static final QName VIEW_METADATA = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "metadata");
65     private static final QName VIEW_VALUE_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "value");
66     private static final QName VIEW_VALUES_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "values");
67     private static final QName VIEW_ASPECTS = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "aspects");
68     private static final QName VIEW_PROPERTIES = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "properties");
69     private static final QName VIEW_ASSOCIATIONS = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "associations");
70     private static final QName VIEW_ACL = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "acl");
71     private static final QName VIEW_ACE = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "ace");
72     private static final QName VIEW_AUTHORITY = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "authority");
73     private static final QName VIEW_PERMISSION = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "permission");
74     private static final QName VIEW_REFERENCE = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "reference");
75     
76     
77     // XML Pull Parser Factory
78
private XmlPullParserFactory factory;
79     
80     // Supporting services
81
private NamespaceService namespaceService;
82     private DictionaryService dictionaryService;
83
84     // Parser Context maintained during each parse
85
private class ParserContext
86     {
87         Importer importer;
88         DictionaryService dictionaryService;
89         Stack JavaDoc<ElementContext> elementStack;
90         Map JavaDoc<String JavaDoc, NodeRef> importIds = new HashMap JavaDoc<String JavaDoc, NodeRef>();
91     }
92     
93
94     /**
95      * Construct
96      */

97     public ViewParser()
98     {
99         try
100         {
101             // Construct Xml Pull Parser Factory
102
factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), this.getClass());
103             factory.setNamespaceAware(true);
104         }
105         catch (XmlPullParserException e)
106         {
107             throw new ImporterException("Failed to initialise view importer", e);
108         }
109     }
110     
111     
112     /**
113      * @param namespaceService the namespace service
114      */

115     public void setNamespaceService(NamespaceService namespaceService)
116     {
117         this.namespaceService = namespaceService;
118     }
119     
120     /**
121      * @param dictionaryService the dictionary service
122      */

123     public void setDictionaryService(DictionaryService dictionaryService)
124     {
125         this.dictionaryService = dictionaryService;
126     }
127     
128     /* (non-Javadoc)
129      * @see org.alfresco.repo.importer.Parser#parse(java.io.Reader, org.alfresco.repo.importer.Importer)
130      */

131     public void parse(Reader JavaDoc viewReader, Importer importer)
132     {
133         try
134         {
135             XmlPullParser xpp = factory.newPullParser();
136             xpp.setInput(viewReader);
137             
138             ParserContext parserContext = new ParserContext();
139             parserContext.importer = importer;
140             parserContext.dictionaryService = dictionaryService;
141             parserContext.elementStack = new Stack JavaDoc<ElementContext>();
142             
143             try
144             {
145                 for (int eventType = xpp.getEventType(); eventType != XmlPullParser.END_DOCUMENT; eventType = xpp.next())
146                 {
147                     switch (eventType)
148                     {
149                         case XmlPullParser.START_TAG:
150                         {
151                             if (xpp.getDepth() == 1)
152                             {
153                                 processRoot(xpp, parserContext);
154                             }
155                             else
156                             {
157                                 processStartElement(xpp, parserContext);
158                             }
159                             break;
160                         }
161                         case XmlPullParser.END_TAG:
162                         {
163                             processEndElement(xpp, parserContext);
164                             break;
165                         }
166                     }
167                 }
168             }
169             catch(Exception JavaDoc e)
170             {
171                 throw new ImporterException("Failed to import package at line " + xpp.getLineNumber() + "; column " + xpp.getColumnNumber() + " due to error: " + e.getMessage(), e);
172             }
173         }
174         catch(XmlPullParserException e)
175         {
176             throw new ImporterException("Failed to parse view", e);
177         }
178     }
179     
180     /**
181      * Process start of xml element
182      *
183      * @param xpp
184      * @param contextStack
185      * @throws XmlPullParserException
186      * @throws IOException
187      */

188     private void processStartElement(XmlPullParser xpp, ParserContext parserContext)
189         throws XmlPullParserException, IOException JavaDoc
190     {
191         // Extract qualified name
192
QName defName = getName(xpp);
193
194         // Process the element
195
Object JavaDoc element = parserContext.elementStack.peek();
196
197         // Handle special view directives
198
if (defName.equals(VIEW_METADATA))
199         {
200             parserContext.elementStack.push(new MetaDataContext(defName, (ElementContext)element));
201         }
202         else if (defName.equals(VIEW_ASPECTS) || defName.equals(VIEW_PROPERTIES) || defName.equals(VIEW_ASSOCIATIONS) || defName.equals(VIEW_ACL))
203         {
204             if (element instanceof NodeItemContext)
205             {
206                 throw new ImporterException("Cannot nest element " + defName + " within " + ((NodeItemContext)element).getElementName());
207             }
208             if (!(element instanceof NodeContext))
209             {
210                 throw new ImporterException("Element " + defName + " can only be declared within a node");
211             }
212             NodeContext node = (NodeContext)element;
213             parserContext.elementStack.push(new NodeItemContext(defName, node));
214
215             // process ACL specific attributes
216
if (defName.equals(VIEW_ACL))
217             {
218                 processACL(xpp, parserContext);
219             }
220         }
221         else
222         {
223             if (element instanceof MetaDataContext)
224             {
225                 processMetaData(xpp, defName, parserContext);
226             }
227             else if (element instanceof ParentContext)
228             {
229                 if (defName.equals(VIEW_REFERENCE))
230                 {
231                     // Process reference
232
processStartReference(xpp, defName, parserContext);
233                 }
234                 else
235                 {
236                     // Process type definition
237
TypeDefinition typeDef = dictionaryService.getType(defName);
238                     if (typeDef == null)
239                     {
240                         throw new ImporterException("Type " + defName + " has not been defined in the Repository dictionary");
241                     }
242                     processStartType(xpp, typeDef, parserContext);
243                 }
244                 return;
245             }
246             else if (element instanceof NodeContext)
247             {
248                 // Process children of node
249
// Note: Process in the following order: aspects, properties and associations
250
Object JavaDoc def = ((NodeContext)element).determineDefinition(defName);
251                 if (def == null)
252                 {
253                     throw new ImporterException("Definition " + defName + " is not valid; cannot find in Repository dictionary");
254                 }
255                 
256                 if (def instanceof AspectDefinition)
257                 {
258                     processAspect(xpp, (AspectDefinition)def, parserContext);
259                     return;
260                 }
261                 else if (def instanceof PropertyDefinition)
262                 {
263                     processProperty(xpp, ((PropertyDefinition)def).getName(), parserContext);
264                     return;
265                 }
266                 else if (def instanceof AssociationDefinition)
267                 {
268                     processStartAssoc(xpp, (AssociationDefinition)def, parserContext);
269                     return;
270                 }
271             }
272             else if (element instanceof NodeItemContext)
273             {
274                 NodeItemContext nodeItem = (NodeItemContext)element;
275                 NodeContext node = nodeItem.getNodeContext();
276                 QName itemName = nodeItem.getElementName();
277                 if (itemName.equals(VIEW_ASPECTS))
278                 {
279                     AspectDefinition def = node.determineAspect(defName);
280                     if (def == null)
281                     {
282                         throw new ImporterException("Aspect name " + defName + " is not valid; cannot find in Repository dictionary");
283                     }
284                     processAspect(xpp, def, parserContext);
285                 }
286                 else if (itemName.equals(VIEW_PROPERTIES))
287                 {
288                     // Note: Allow properties which do not have a data dictionary definition
289
processProperty(xpp, defName, parserContext);
290                 }
291                 else if (itemName.equals(VIEW_ASSOCIATIONS))
292                 {
293                     AssociationDefinition def = (AssociationDefinition)node.determineAssociation(defName);
294                     if (def == null)
295                     {
296                         throw new ImporterException("Association name " + defName + " is not valid; cannot find in Repository dictionary");
297                     }
298                     processStartAssoc(xpp, (AssociationDefinition)def, parserContext);
299                 }
300                 else if (itemName.equals(VIEW_ACL))
301                 {
302                     processAccessControlEntry(xpp, parserContext);
303                 }
304             }
305         }
306     }
307
308     /**
309      * Process Root
310      *
311      * @param xpp
312      * @param parentRef
313      * @param childAssocType
314      * @param configuration
315      * @param progress
316      * @param contextStack
317      * @throws XmlPullParserException
318      * @throws IOException
319      */

320     private void processRoot(XmlPullParser xpp, ParserContext parserContext)
321         throws XmlPullParserException, IOException JavaDoc
322     {
323         ParentContext parent = new ParentContext(getName(xpp), parserContext.dictionaryService, parserContext.importer);
324         parserContext.elementStack.push(parent);
325         
326         if (logger.isDebugEnabled())
327             logger.debug(indentLog("Pushed " + parent, parserContext.elementStack.size() -1));
328     }
329
330     /**
331      * Process meta-data
332      *
333      * @param xpp
334      * @param metaDataName
335      * @param contextStack
336      * @throws XmlPullParserException
337      * @throws IOException
338      */

339     private void processMetaData(XmlPullParser xpp, QName metaDataName, ParserContext parserContext)
340         throws XmlPullParserException, IOException JavaDoc
341     {
342         MetaDataContext metaData = (MetaDataContext)parserContext.elementStack.peek();
343
344         String JavaDoc value = null;
345         
346         int eventType = xpp.next();
347         if (eventType == XmlPullParser.TEXT)
348         {
349             // Extract value
350
value = xpp.getText();
351             eventType = xpp.next();
352         }
353         if (eventType != XmlPullParser.END_TAG)
354         {
355             throw new ImporterException("Meta data element " + metaDataName + " is missing end tag");
356         }
357
358         metaData.setProperty(metaDataName, value);
359     }
360     
361     /**
362      * Process start of a node definition
363      *
364      * @param xpp
365      * @param typeDef
366      * @param contextStack
367      * @throws XmlPullParserException
368      * @throws IOException
369      */

370     private void processStartType(XmlPullParser xpp, TypeDefinition typeDef, ParserContext parserContext)
371         throws XmlPullParserException, IOException JavaDoc
372     {
373         ParentContext parent = (ParentContext)parserContext.elementStack.peek();
374         NodeContext node = new NodeContext(typeDef.getName(), parent, typeDef);
375
376         // Extract child name if explicitly defined
377
String JavaDoc childName = xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_CHILD_NAME_ATTR);
378         if (childName != null && childName.length() > 0)
379         {
380             node.setChildName(childName);
381         }
382
383         // Extract import id if explicitly defined
384
String JavaDoc importId = xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_ID_ATTR);
385         if (importId != null && importId.length() > 0)
386         {
387             node.setImportId(importId);
388         }
389         
390         parserContext.elementStack.push(node);
391         
392         if (logger.isDebugEnabled())
393             logger.debug(indentLog("Pushed " + node, parserContext.elementStack.size() -1));
394     }
395
396     /**
397      * Process start reference
398      *
399      * @param xpp
400      * @param typeDef
401      * @param contextStack
402      * @throws XmlPullParserException
403      * @throws IOException
404      */

405     private void processStartReference(XmlPullParser xpp, QName refName, ParserContext parserContext)
406         throws XmlPullParserException, IOException JavaDoc
407     {
408         ParentContext parent = (ParentContext)parserContext.elementStack.peek();
409         NodeContext node = new NodeContext(refName, parent, null);
410         node.setReference(true);
411         
412         // Extract Import scoped reference Id if explicitly defined
413
String JavaDoc idRefAttr = xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_IDREF_ATTR);
414         String JavaDoc pathRefAttr = xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_PATHREF_ATTR);
415         String JavaDoc nodeRefAttr = xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_NODEREF_ATTR);
416
417         if ((idRefAttr != null && idRefAttr.length() > 0) && (pathRefAttr != null && pathRefAttr.length() > 0) && (nodeRefAttr != null && nodeRefAttr.length() > 0))
418         {
419             // Do not support both IDREF and PATHREF
420
throw new ImporterException("Only one of " + VIEW_IDREF_ATTR + " or " + VIEW_PATHREF_ATTR + " or " + VIEW_NODEREF_ATTR + " can be specified.");
421         }
422         if (nodeRefAttr != null)
423         {
424             NodeRef nodeRef = new NodeRef(nodeRefAttr);
425             node.setUUID(nodeRef.getId());
426         }
427         else if (idRefAttr != null && idRefAttr.length() > 0)
428         {
429             // retrieve uuid from previously imported node
430
NodeRef nodeRef = getImportReference(parserContext, idRefAttr);
431             if (nodeRef == null)
432             {
433                 throw new ImporterException("Cannot find node referenced by id " + idRefAttr);
434             }
435             node.setUUID(nodeRef.getId());
436         }
437         else if (pathRefAttr != null && pathRefAttr.length() > 0)
438         {
439             NodeRef referencedRef = parserContext.importer.resolvePath(pathRefAttr);
440             if (referencedRef == null)
441             {
442                 throw new ImporterException("Cannot find node referenced by path " + pathRefAttr);
443             }
444             node.setUUID(referencedRef.getId());
445         }
446         
447         // Extract child name if explicitly defined
448
String JavaDoc childName = xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_CHILD_NAME_ATTR);
449         if (childName != null && childName.length() > 0)
450         {
451             node.setChildName(childName);
452         }
453
454         // Extract import id if explicitly defined
455
String JavaDoc importId = xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_ID_ATTR);
456         if (importId != null && importId.length() > 0)
457         {
458             node.setImportId(importId);
459         }
460
461         parserContext.elementStack.push(node);
462         
463         if (logger.isDebugEnabled())
464             logger.debug(indentLog("Pushed Reference " + node, parserContext.elementStack.size() -1));
465     }
466     
467     /**
468      * Process aspect definition
469      *
470      * @param xpp
471      * @param aspectDef
472      * @param contextStack
473      * @throws XmlPullParserException
474      * @throws IOException
475      */

476     private void processAspect(XmlPullParser xpp, AspectDefinition aspectDef, ParserContext parserContext)
477         throws XmlPullParserException, IOException JavaDoc
478     {
479         NodeContext node = peekNodeContext(parserContext.elementStack);
480         node.addAspect(aspectDef);
481         
482         int eventType = xpp.next();
483         if (eventType != XmlPullParser.END_TAG)
484         {
485             throw new ImporterException("Aspect " + aspectDef.getName() + " definition is not valid - it cannot contain any elements");
486         }
487         
488         if (logger.isDebugEnabled())
489             logger.debug(indentLog("Processed aspect " + aspectDef.getName(), parserContext.elementStack.size()));
490     }
491     
492     /**
493      * Process ACL definition
494      *
495      * @param xpp
496      * @param contextStack
497      */

498     private void processACL(XmlPullParser xpp, ParserContext parserContext)
499     {
500         NodeContext node = peekNodeContext(parserContext.elementStack);
501         
502         String JavaDoc strInherit = xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_INHERIT_PERMISSIONS_ATTR);
503         if (strInherit != null)
504         {
505             Boolean JavaDoc inherit = Boolean.valueOf(strInherit);
506             if (!inherit)
507             {
508                 node.setInheritPermissions(false);
509             }
510         }
511     }
512     
513     /**
514      * Process ACE definition
515      *
516      * @param xpp
517      * @param contextStack
518      * @throws XmlPullParserException
519      * @throws IOException
520      */

521     private void processAccessControlEntry(XmlPullParser xpp, ParserContext parserContext)
522         throws XmlPullParserException, IOException JavaDoc
523     {
524         NodeContext node = peekNodeContext(parserContext.elementStack);
525
526         QName defName = getName(xpp);
527         if (!defName.equals(VIEW_ACE))
528         {
529             throw new ImporterException("Expected start element " + VIEW_ACE);
530         }
531
532         // extract Access Status
533
String JavaDoc access = xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_ACCESS_STATUS_ATTR);
534         AccessStatus accessStatus = (access == null) ? AccessStatus.ALLOWED : AccessStatus.valueOf(AccessStatus.class, access);
535         if (accessStatus == null)
536         {
537             throw new ImporterException("Permission access status '" + access + "' is not recognised.");
538         }
539
540         // extract authority and permission
541
String JavaDoc authority = null;
542         String JavaDoc permission = null;
543         int eventType = xpp.next();
544         while (eventType != XmlPullParser.END_TAG)
545         {
546             if (eventType == XmlPullParser.START_TAG)
547             {
548                 defName = getName(xpp);
549                 if (defName.equals(VIEW_AUTHORITY))
550                 {
551                     eventType = xpp.next();
552                     if (eventType != XmlPullParser.TEXT)
553                     {
554                         throw new ImporterException("Element " + VIEW_AUTHORITY + " must have a value");
555                     }
556                     authority = xpp.getText();
557                 }
558                 else if (defName.equals(VIEW_PERMISSION))
559                 {
560                     eventType = xpp.next();
561                     if (eventType != XmlPullParser.TEXT)
562                     {
563                         throw new ImporterException("Element " + VIEW_PERMISSION + " must have a value");
564                     }
565                     permission = xpp.getText();
566                 }
567                 else
568                 {
569                     throw new ImporterException("Expected start element " + VIEW_AUTHORITY + " or " + VIEW_PERMISSION);
570                 }
571                 
572                 eventType = xpp.next();
573                 if (eventType != XmlPullParser.END_TAG)
574                 {
575                     throw new ImporterException("Expected end element " + defName);
576                 }
577                 QName endDefName = getName(xpp);
578                 if (!defName.equals(endDefName))
579                 {
580                     throw new ImporterException("Expected end element " + defName);
581                 }
582             }
583             
584             eventType = xpp.next();
585         }
586
587         // validate authority and permission
588
if (authority == null || authority.length() == 0)
589         {
590             throw new ImporterException("Authority must be specified");
591         }
592         if (permission == null || permission.length() == 0)
593         {
594             throw new ImporterException("Permisssion must be specified");
595         }
596
597         // extract end of ace
598
defName = getName(xpp);
599         if (!defName.equals(VIEW_ACE))
600         {
601             throw new ImporterException("Expected end element " + VIEW_ACE);
602         }
603         
604         // update node context
605
node.addAccessControlEntry(accessStatus, authority, permission);
606     }
607     
608     /**
609      * Process property definition
610      *
611      * @param xpp
612      * @param propDef
613      * @param contextStack
614      * @throws XmlPullParserException
615      * @throws IOException
616      */

617     private void processProperty(XmlPullParser xpp, QName propertyName, ParserContext parserContext)
618         throws XmlPullParserException, IOException JavaDoc
619     {
620         NodeContext node = peekNodeContext(parserContext.elementStack);
621
622         // Extract single value
623
String JavaDoc value = "";
624         int eventType = xpp.next();
625         if (eventType == XmlPullParser.TEXT)
626         {
627             value = xpp.getText();
628             eventType = xpp.next();
629         }
630         if (eventType == XmlPullParser.END_TAG)
631         {
632             node.addProperty(propertyName, value);
633         }
634         else
635         {
636             // Extract collection, if specified
637
boolean isCollection = false;
638             if (eventType == XmlPullParser.START_TAG)
639             {
640                 QName name = getName(xpp);
641                 if (name.equals(VIEW_VALUES_QNAME))
642                 {
643                     node.addPropertyCollection(propertyName);
644                     isCollection = true;
645                     eventType = xpp.next();
646                     if (eventType == XmlPullParser.TEXT)
647                     {
648                         eventType = xpp.next();
649                     }
650                 }
651             }
652             
653             // Extract decorated value
654
while (eventType == XmlPullParser.START_TAG)
655             {
656                 QName name = getName(xpp);
657                 if (!name.equals(VIEW_VALUE_QNAME))
658                 {
659                     throw new ImporterException("Invalid view structure - expected element " + VIEW_VALUE_QNAME + " for property " + propertyName);
660                 }
661                 QName datatype = QName.createQName(xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_DATATYPE_ATTR), namespaceService);
662                 Boolean JavaDoc isNull = Boolean.valueOf(xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_ISNULL_ATTR));
663                 String JavaDoc decoratedValue = isNull ? null : "";
664                 eventType = xpp.next();
665                 if (eventType == XmlPullParser.TEXT)
666                 {
667                     decoratedValue = xpp.getText();
668                     eventType = xpp.next();
669                 }
670                 if (eventType == XmlPullParser.END_TAG)
671                 {
672                     node.addProperty(propertyName, decoratedValue);
673                     if (datatype != null)
674                     {
675                         node.addDatatype(propertyName, dictionaryService.getDataType(datatype));
676                     }
677                 }
678                 else
679                 {
680                     throw new ImporterException("Value for property " + propertyName + " has not been defined correctly - missing end tag");
681                 }
682                 eventType = xpp.next();
683                 if (eventType == XmlPullParser.TEXT)
684                 {
685                     eventType = xpp.next();
686                 }
687             }
688     
689             // End of value
690
if (eventType != XmlPullParser.END_TAG)
691             {
692                 throw new ImporterException("Invalid view structure - property " + propertyName + " definition is invalid");
693             }
694             
695             // End of collection
696
if (isCollection)
697             {
698                 eventType = xpp.next();
699                 if (eventType == XmlPullParser.TEXT)
700                 {
701                     eventType = xpp.next();
702                 }
703                 if (eventType != XmlPullParser.END_TAG)
704                 {
705                     throw new ImporterException("Invalid view structure - property " + propertyName + " definition is invalid");
706                 }
707             }
708         }
709         
710         if (logger.isDebugEnabled())
711             logger.debug(indentLog("Processed property " + propertyName, parserContext.elementStack.size()));
712     }
713
714     /**
715      * Process start of association definition
716      *
717      * @param xpp
718      * @param AssocDef
719      * @param contextStack
720      * @throws XmlPullParserException
721      * @throws IOException
722      */

723     private void processStartAssoc(XmlPullParser xpp, AssociationDefinition assocDef, ParserContext parserContext)
724         throws XmlPullParserException, IOException JavaDoc
725     {
726         NodeContext node = peekNodeContext(parserContext.elementStack);
727         importNode(parserContext, node);
728     
729         // Construct Child Association Context
730
ParentContext parent = new ParentContext(assocDef.getName(), node, assocDef);
731         parserContext.elementStack.push(parent);
732         
733         if (logger.isDebugEnabled())
734             logger.debug(indentLog("Pushed " + parent, parserContext.elementStack.size() -1));
735     }
736     
737     /**
738      * Process end of xml element
739      *
740      * @param xpp
741      * @param contextStack
742      */

743     private void processEndElement(XmlPullParser xpp, ParserContext parserContext)
744     {
745         ElementContext element = parserContext.elementStack.peek();
746         if (element.getElementName().getLocalName().equals(xpp.getName()) &&
747             element.getElementName().getNamespaceURI().equals(xpp.getNamespace()))
748         {
749             element = parserContext.elementStack.pop();
750             
751             if (logger.isDebugEnabled())
752                 logger.debug(indentLog("Popped " + element, parserContext.elementStack.size()));
753
754             if (element instanceof NodeContext)
755             {
756                 processEndType(parserContext, (NodeContext)element);
757             }
758             else if (element instanceof ParentContext)
759             {
760                 processEndAssoc(parserContext, (ParentContext)element);
761             }
762             else if (element instanceof MetaDataContext)
763             {
764                 processEndMetaData(parserContext, (MetaDataContext)element);
765             }
766         }
767     }
768     
769     /**
770      * Process end of the type definition
771      *
772      * @param node
773      */

774     private void processEndType(ParserContext parserContext, NodeContext node)
775     {
776         importNode(parserContext, node);
777         NodeRef nodeRef = node.getNodeRef();
778         node.getImporter().childrenImported(nodeRef);
779     }
780
781     /**
782      * Process end of the child association
783      *
784      * @param context
785      */

786     private void processEndAssoc(ParserContext parserContext, ParentContext parent)
787     {
788     }
789
790     /**
791      * Process end of meta data
792      *
793      * @param context
794      */

795     private void processEndMetaData(ParserContext parserContext, MetaDataContext context)
796     {
797         context.getImporter().importMetaData(context.getProperties());
798     }
799     
800
801     /**
802      * Import node
803      *
804      * @param parserContext parser context
805      * @param node node context
806      */

807     private void importNode(ParserContext parserContext, NodeContext node)
808     {
809         if (node.getNodeRef() == null)
810         {
811             // Import Node
812
NodeRef nodeRef = node.getImporter().importNode(node);
813             node.setNodeRef(nodeRef);
814             
815             // Maintain running list of "import" scoped ids
816
String JavaDoc importId = node.getImportId();
817             if (importId != null && importId.length() > 0)
818             {
819                 createImportReference(parserContext, importId, nodeRef);
820             }
821         }
822     }
823     
824     /**
825      * Maps an Import Id to a Node Reference
826      *
827      * @param importId import Id
828      * @param nodeRef node reference
829      */

830     private void createImportReference(ParserContext parserContext, String JavaDoc importId, NodeRef nodeRef)
831     {
832         if (parserContext.importIds.containsKey(importId))
833         {
834             throw new ImporterException("Import id " + importId + " already specified within import file");
835         }
836         parserContext.importIds.put(importId, nodeRef);
837     }
838
839     /**
840      * Gets the Node Reference for the specified Import Id
841      *
842      * @param importId the import id
843      * @return the node reference
844      */

845     private NodeRef getImportReference(ParserContext parserContext, String JavaDoc importId)
846     {
847         return parserContext.importIds.get(importId);
848     }
849
850     /**
851      * Get parent Node Context
852      *
853      * @param contextStack context stack
854      * @return node context
855      */

856     private NodeContext peekNodeContext(Stack JavaDoc<ElementContext> contextStack)
857     {
858         ElementContext element = contextStack.peek();
859         if (element instanceof NodeContext)
860         {
861             return (NodeContext)element;
862         }
863         else if (element instanceof NodeItemContext)
864         {
865             return ((NodeItemContext)element).getNodeContext();
866         }
867         throw new ImporterException("Internal error: Failed to retrieve node context");
868     }
869     
870     /**
871      * Helper to create Qualified name from current xml element
872      *
873      * @param xpp
874      * @return
875      */

876     private QName getName(XmlPullParser xpp)
877     {
878         // Ensure namespace is valid
879
String JavaDoc uri = xpp.getNamespace();
880         if (namespaceService.getURIs().contains(uri) == false)
881         {
882             throw new ImporterException("Namespace URI " + uri + " has not been defined in the Repository dictionary");
883         }
884         
885         // Construct name
886
String JavaDoc name = xpp.getName();
887         return QName.createQName(uri, name);
888     }
889
890     /**
891      * Helper to indent debug output
892      *
893      * @param msg
894      * @param depth
895      * @return
896      */

897     private String JavaDoc indentLog(String JavaDoc msg, int depth)
898     {
899         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(1024);
900         for (int i = 0; i < depth; i++)
901         {
902             buf.append(' ');
903         }
904         buf.append(msg);
905         return buf.toString();
906     }
907     
908 }
909
Popular Tags