    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.dom;
    019
    020import org.apache.commons.jxpath.ri.Compiler;
    021import org.apache.commons.jxpath.ri.QName;
    022import org.apache.commons.jxpath.ri.compiler.NodeTest;
    023import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
    024import org.apache.commons.jxpath.ri.model.NodePointer;
    025import org.apache.commons.jxpath.util.TypeUtils;
    026import org.w3c.dom.Attr;
    027
    028/**
    029 * A Pointer that points to a DOM {@link Attr} node. Because the underlying DOM Attr is not Serializable, neither is this pointer class truly so.
    030 */
    031public class DOMAttributePointer extends NodePointer {
    032
    033    private static final long serialVersionUID = 1115085175427555951L;
    034
    035    /**
    036     * A DOM {@link Attr} node.
    037     */
    038    private final Attr attr;
    039
    040    /**
    041     * Constructs a new DOMAttributePointer.
    042     *
    043     * @param parent pointer
    044     * @param attr   pointed
    045     */
    046    public DOMAttributePointer(final NodePointer parent, final Attr attr) {
    047        super(parent);
    048        this.attr = attr;
    049    }
    050
    051    @Override
    052    public String asPath() {
    053        final StringBuilder buffer = new StringBuilder();
    054        if (parent != null) {
    055            buffer.append(parent.asPath());
    056            if (buffer.length() == 0 || buffer.charAt(buffer.length() - 1) != '/') {
    057                buffer.append('/');
    058            }
    059        }
    060        buffer.append('@');
    061        buffer.append(getName());
    062        return buffer.toString();
    063    }
    064
    065    @Override
    066    public int compareChildNodePointers(final NodePointer pointer1, final NodePointer pointer2) {
    067        // Won't happen - attributes don't have children
    068        return 0;
    069    }
    070
    071    @Override
    072    public boolean equals(final Object object) {
    073        return object == this || object instanceof DOMAttributePointer && attr == ((DOMAttributePointer) object).attr;
    074    }
    075
    076    @Override
    077    public Object getBaseValue() {
    078        return attr;
    079    }
    080
    081    @Override
    082    public Object getImmediateNode() {
    083        return attr;
    084    }
    085
    086    @Override
    087    public int getLength() {
    088        return 1;
    089    }
    090
    091    @Override
    092    public QName getName() {
    093        return new QName(DOMNodePointer.getPrefix(attr), DOMNodePointer.getLocalName(attr));
    094    }
    095
    096    @Override
    097    public String getNamespaceURI() {
    098        final String prefix = DOMNodePointer.getPrefix(attr);
    099        return prefix == null ? null : parent.getNamespaceURI(prefix);
    100    }
    101
    102    @Override
    103    public Object getValue() {
    104        final String value = attr.getValue();
    105        if (value == null || value.isEmpty() && !attr.getSpecified()) {
    106            return null;
    107        }
    108        return value;
    109    }
    110
    111    @Override
    112    public int hashCode() {
    113        return System.identityHashCode(attr);
    114    }
    115
    116    @Override
    117    public boolean isActual() {
    118        return true;
    119    }
    120
    121    @Override
    122    public boolean isCollection() {
    123        return false;
    124    }
    125
    126    @Override
    127    public boolean isLeaf() {
    128        return true;
    129    }
    130
    131    @Override
    132    public void remove() {
    133        attr.getOwnerElement().removeAttributeNode(attr);
    134    }
    135
    136    /**
    137     * Sets the value of this attribute.
    138     *
    139     * @param value to set
    140     */
    141    @Override
    142    public void setValue(final Object value) {
    143        attr.setValue((String) TypeUtils.convert(value, String.class));
    144    }
    145
    146    @Override
    147    public boolean testNode(final NodeTest nodeTest) {
    148        return nodeTest == null || nodeTest instanceof NodeTypeTest && ((NodeTypeTest) nodeTest).getNodeType() == Compiler.NODE_TYPE_NODE;
    149    }
    150}