View Javadoc

1   /*
2    * Copyright 1999-2004 The Apache Software Foundation
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.jxpath.ri.model.beans;
17  
18  import java.util.Locale;
19  
20  import org.apache.commons.jxpath.JXPathException;
21  import org.apache.commons.jxpath.ri.Compiler;
22  import org.apache.commons.jxpath.ri.QName;
23  import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
24  import org.apache.commons.jxpath.ri.compiler.NodeTest;
25  import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
26  import org.apache.commons.jxpath.ri.model.NodeIterator;
27  import org.apache.commons.jxpath.ri.model.NodePointer;
28  import org.apache.commons.jxpath.util.ValueUtils;
29  
30  /***
31   * A pointer describing a node that has properties, each of which could be
32   * a collection.
33   *
34   * @author Dmitri Plotnikov
35   * @version $Revision: 1.19 $ $Date: 2004/04/04 22:06:36 $
36   */
37  public abstract class PropertyOwnerPointer extends NodePointer {
38  
39      public NodeIterator childIterator(
40          NodeTest test,
41          boolean reverse,
42          NodePointer startWith) 
43      {
44          if (test == null) {
45              return createNodeIterator(null, reverse, startWith);
46          }
47          else if (test instanceof NodeNameTest) {
48              NodeNameTest nodeNameTest = (NodeNameTest) test;
49              QName testName = nodeNameTest.getNodeName();
50              String property;
51              if (!isDefaultNamespace(testName.getPrefix())) {
52                  return null;
53              }
54              else if (nodeNameTest.isWildcard()) {
55                  property = null;
56              }
57              else {
58                  property = testName.getName();
59              }
60              return createNodeIterator(property, reverse, startWith);
61          }
62          else if (test instanceof NodeTypeTest) {
63              if (((NodeTypeTest) test).getNodeType()
64                  == Compiler.NODE_TYPE_NODE) {
65                  return createNodeIterator(null, reverse, startWith);
66              }
67          }
68          return null;
69      }
70  
71      public NodeIterator createNodeIterator(
72                  String property,
73                  boolean reverse,
74                  NodePointer startWith) 
75      {
76          return new PropertyIterator(this, property, reverse, startWith);
77      }
78  
79      public NodeIterator attributeIterator(QName name) {
80          return new BeanAttributeIterator(this, name);
81      }
82  
83      protected PropertyOwnerPointer(NodePointer parent, Locale locale) {
84          super(parent, locale);
85      }
86  
87      protected PropertyOwnerPointer(NodePointer parent) {
88          super(parent);
89      }
90  
91      public void setIndex(int index) {
92          if (this.index != index) {
93              super.setIndex(index);
94              value = UNINITIALIZED;
95          }
96      }
97  
98      private static final Object UNINITIALIZED = new Object();
99  
100     private Object value = UNINITIALIZED;
101     public Object getImmediateNode() {
102         if (value == UNINITIALIZED) {
103             if (index == WHOLE_COLLECTION) {
104                 value = ValueUtils.getValue(getBaseValue());
105             }
106             else {
107                 value = ValueUtils.getValue(getBaseValue(), index);
108             }
109         }
110         return value;
111     }
112 
113     public abstract QName getName();
114 
115     /***
116      * Throws an exception if you try to change the root element, otherwise
117      * forwards the call to the parent pointer.
118      */
119     public void setValue(Object value) {
120         this.value = value;
121         if (parent.isContainer()) {
122             parent.setValue(value);
123         }
124         else if (parent != null) {
125             if (index == WHOLE_COLLECTION) {
126                 throw new UnsupportedOperationException(
127                     "Cannot setValue of an object that is not "
128                         + "some other object's property");
129             }
130             else {
131                 throw new JXPathException(
132                     "The specified collection element does not exist: " + this);
133             }
134         }
135         else {
136             throw new UnsupportedOperationException(
137                 "Cannot replace the root object");
138         }
139     }
140 
141     /***
142      * If this is a root node pointer, throws an exception; otherwise
143      * forwards the call to the parent node.
144      */
145     public void remove() {
146         this.value = null;
147         if (parent != null) {
148             parent.remove();
149         }
150         else {
151             throw new UnsupportedOperationException(
152                 "Cannot remove an object that is not "
153                     + "some other object's property or a collection element");
154         }
155     }
156 
157     public abstract PropertyPointer getPropertyPointer();
158     
159     /***
160      * @return true if the property owner can set a property "does not exist".
161      *         A good example is a Map. You can always assign a value to any
162      *         key even if it has never been "declared".
163      */
164     public boolean isDynamicPropertyDeclarationSupported() {
165         return false;
166     }
167 
168     public int compareChildNodePointers(
169         NodePointer pointer1,
170         NodePointer pointer2) 
171     {
172         int r =
173             pointer1.getName().toString().compareTo(
174                 pointer2.getName().toString());
175         if (r != 0) {
176             return r;
177         }
178         return pointer1.getIndex() - pointer2.getIndex();
179     }
180 }