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. import org.apache.commons.jxpath.JXPathContext;
  18. import org.apache.commons.jxpath.JXPathException;
  19. import org.apache.commons.jxpath.ri.QName;
  20. import org.apache.commons.jxpath.ri.model.NodePointer;
  21. /**
  22. * @author Dmitri Plotnikov
  23. * @version $Revision: 1.18 $ $Date: 2004/03/25 03:49:50 $
  24. */
  25. public class NullPropertyPointer extends PropertyPointer {
  26. private String propertyName = "*";
  27. private boolean byNameAttribute = false;
  28. /**
  29. */
  30. public NullPropertyPointer(NodePointer parent) {
  31. super(parent);
  32. }
  33. public QName getName() {
  34. return new QName(propertyName);
  35. }
  36. public void setPropertyIndex(int index) {
  37. }
  38. public int getLength() {
  39. return 0;
  40. }
  41. public Object getBaseValue() {
  42. return null;
  43. }
  44. public Object getImmediateNode() {
  45. return null;
  46. }
  47. public boolean isLeaf() {
  48. return true;
  49. }
  50. public NodePointer getValuePointer() {
  51. return new NullPointer(this, new QName(getPropertyName()));
  52. }
  53. protected boolean isActualProperty() {
  54. return false;
  55. }
  56. public boolean isActual() {
  57. return false;
  58. }
  59. public boolean isContainer() {
  60. return true;
  61. }
  62. public void setValue(Object value) {
  63. if (parent == null || parent.isContainer()) {
  64. throw new JXPathException(
  65. "Cannot set property "
  66. + asPath()
  67. + ", the target object is null");
  68. }
  69. else if (parent instanceof PropertyOwnerPointer &&
  70. ((PropertyOwnerPointer) parent).
  71. isDynamicPropertyDeclarationSupported()){
  72. // If the parent property owner can create
  73. // a property automatically - let it do so
  74. PropertyPointer propertyPointer =
  75. ((PropertyOwnerPointer) parent).getPropertyPointer();
  76. propertyPointer.setPropertyName(propertyName);
  77. propertyPointer.setValue(value);
  78. }
  79. else {
  80. throw new JXPathException(
  81. "Cannot set property "
  82. + asPath()
  83. + ", path does not match a changeable location");
  84. }
  85. }
  86. public NodePointer createPath(JXPathContext context) {
  87. NodePointer newParent = parent.createPath(context);
  88. if (isAttribute()) {
  89. return newParent.createAttribute(context, getName());
  90. }
  91. else {
  92. // Consider these two use cases:
  93. // 1. The parent pointer of NullPropertyPointer is
  94. // a PropertyOwnerPointer other than NullPointer. When we call
  95. // createPath on it, it most likely returns itself. We then
  96. // take a PropertyPointer from it and get the PropertyPointer
  97. // to expand the collection for the corresponsing property.
  98. //
  99. // 2. The parent pointer of NullPropertyPointer is a NullPointer.
  100. // When we call createPath, it may return a PropertyOwnerPointer
  101. // or it may return anything else, like a DOMNodePointer.
  102. // In the former case we need to do exactly what we did in use
  103. // case 1. In the latter case, we simply request that the
  104. // non-property pointer expand the collection by itself.
  105. if (newParent instanceof PropertyOwnerPointer) {
  106. PropertyOwnerPointer pop = (PropertyOwnerPointer) newParent;
  107. newParent = pop.getPropertyPointer();
  108. }
  109. return newParent.createChild(context, getName(), getIndex());
  110. }
  111. }
  112. public NodePointer createPath(JXPathContext context, Object value) {
  113. NodePointer newParent = parent.createPath(context);
  114. if (isAttribute()) {
  115. NodePointer pointer = newParent.createAttribute(context, getName());
  116. pointer.setValue(value);
  117. return pointer;
  118. }
  119. else {
  120. if (newParent instanceof PropertyOwnerPointer) {
  121. PropertyOwnerPointer pop = (PropertyOwnerPointer) newParent;
  122. newParent = pop.getPropertyPointer();
  123. }
  124. return newParent.createChild(context, getName(), index, value);
  125. }
  126. }
  127. public NodePointer createChild(
  128. JXPathContext context,
  129. QName name,
  130. int index)
  131. {
  132. return createPath(context).createChild(context, name, index);
  133. }
  134. public NodePointer createChild(
  135. JXPathContext context,
  136. QName name,
  137. int index,
  138. Object value)
  139. {
  140. return createPath(context).createChild(context, name, index, value);
  141. }
  142. public String getPropertyName() {
  143. return propertyName;
  144. }
  145. public void setPropertyName(String propertyName) {
  146. this.propertyName = propertyName;
  147. }
  148. public void setNameAttributeValue(String attributeValue) {
  149. this.propertyName = attributeValue;
  150. byNameAttribute = true;
  151. }
  152. public boolean isCollection() {
  153. return getIndex() != WHOLE_COLLECTION;
  154. }
  155. public int getPropertyCount() {
  156. return 0;
  157. }
  158. public String[] getPropertyNames() {
  159. return new String[0];
  160. }
  161. public String asPath() {
  162. if (!byNameAttribute) {
  163. return super.asPath();
  164. }
  165. else {
  166. StringBuffer buffer = new StringBuffer();
  167. buffer.append(getImmediateParentPointer().asPath());
  168. buffer.append("[@name='");
  169. buffer.append(escape(getPropertyName()));
  170. buffer.append("']");
  171. if (index != WHOLE_COLLECTION) {
  172. buffer.append('[').append(index + 1).append(']');
  173. }
  174. return buffer.toString();
  175. }
  176. }
  177. private String escape(String string) {
  178. int index = string.indexOf('\'');
  179. while (index != -1) {
  180. string =
  181. string.substring(0, index)
  182. + "'"
  183. + string.substring(index + 1);
  184. index = string.indexOf('\'');
  185. }
  186. index = string.indexOf('\"');
  187. while (index != -1) {
  188. string =
  189. string.substring(0, index)
  190. + """
  191. + string.substring(index + 1);
  192. index = string.indexOf('\"');
  193. }
  194. return string;
  195. }
  196. }