001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.jxpath.ri.model.container; 019 020import java.util.Locale; 021 022import org.apache.commons.jxpath.Container; 023import org.apache.commons.jxpath.ri.QName; 024import org.apache.commons.jxpath.ri.compiler.NodeTest; 025import org.apache.commons.jxpath.ri.model.NodeIterator; 026import org.apache.commons.jxpath.ri.model.NodePointer; 027import org.apache.commons.jxpath.util.ValueUtils; 028 029/** 030 * Transparent pointer to a Container. The {@link #getValue()} method returns the contents of the container, rather than the container itself. 031 */ 032public class ContainerPointer extends NodePointer { 033 034 private static final long serialVersionUID = 6140752946621686118L; 035 036 /** 037 * A Container. 038 */ 039 private final Container container; 040 041 /** 042 * Supports {@link #getImmediateValuePointer()}. 043 */ 044 private NodePointer valuePointer; 045 046 /** 047 * Constructs a new ContainerPointer. 048 * 049 * @param container Container object 050 * @param locale Locale 051 */ 052 public ContainerPointer(final Container container, final Locale locale) { 053 super(null, locale); 054 this.container = container; 055 } 056 057 /** 058 * Constructs a new ContainerPointer. 059 * 060 * @param parent parent pointer 061 * @param container Container object 062 */ 063 public ContainerPointer(final NodePointer parent, final Container container) { 064 super(parent); 065 this.container = container; 066 } 067 068 @Override 069 public String asPath() { 070 return parent == null ? "/" : parent.asPath(); 071 } 072 073 @Override 074 public NodeIterator attributeIterator(final QName qName) { 075 return getValuePointer().attributeIterator(qName); 076 } 077 078 @Override 079 public NodeIterator childIterator(final NodeTest test, final boolean reverse, final NodePointer startWith) { 080 return getValuePointer().childIterator(test, reverse, startWith); 081 } 082 083 @Override 084 public int compareChildNodePointers(final NodePointer pointer1, final NodePointer pointer2) { 085 return pointer1.getIndex() - pointer2.getIndex(); 086 } 087 088 @Override 089 public boolean equals(final Object object) { 090 if (object == this) { 091 return true; 092 } 093 if (!(object instanceof ContainerPointer)) { 094 return false; 095 } 096 final ContainerPointer other = (ContainerPointer) object; 097 return container == other.container && index == other.index; 098 } 099 100 @Override 101 public Object getBaseValue() { 102 return container; 103 } 104 105 @Override 106 public Object getImmediateNode() { 107 final Object value = getBaseValue(); 108 if (index != WHOLE_COLLECTION) { 109 return index >= 0 && index < getLength() ? ValueUtils.getValue(value, index) : null; 110 } 111 return ValueUtils.getValue(value); 112 } 113 114 @Override 115 public NodePointer getImmediateValuePointer() { 116 if (valuePointer == null) { 117 final Object value = getImmediateNode(); 118 valuePointer = newChildNodePointer(this, getName(), value); 119 } 120 return valuePointer; 121 } 122 123 @Override 124 public int getLength() { 125 final Object value = getBaseValue(); 126 return value == null ? 1 : ValueUtils.getLength(value); 127 } 128 129 @Override 130 public QName getName() { 131 return null; 132 } 133 134 @Override 135 public String getNamespaceURI(final String prefix) { 136 return getValuePointer().getNamespaceURI(prefix); 137 } 138 139 @Override 140 public int hashCode() { 141 return System.identityHashCode(container) + index; 142 } 143 144 @Override 145 public boolean isCollection() { 146 final Object value = getBaseValue(); 147 return value != null && ValueUtils.isCollection(value); 148 } 149 150 /** 151 * This type of node is auxiliary. 152 * 153 * @return {@code true}. 154 */ 155 @Override 156 public boolean isContainer() { 157 return true; 158 } 159 160 @Override 161 public boolean isLeaf() { 162 return getValuePointer().isLeaf(); 163 } 164 165 @Override 166 public NodeIterator namespaceIterator() { 167 return getValuePointer().namespaceIterator(); 168 } 169 170 @Override 171 public NodePointer namespacePointer(final String namespace) { 172 return getValuePointer().namespacePointer(namespace); 173 } 174 175 @Override 176 public void setValue(final Object value) { 177 // TODO: what if this is a collection? 178 container.setValue(value); 179 } 180 181 @Override 182 public boolean testNode(final NodeTest nodeTest) { 183 return getValuePointer().testNode(nodeTest); 184 } 185}