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 */
017package org.apache.commons.jxpath.ri.axes;
018
019import org.apache.commons.jxpath.ri.Compiler;
020import org.apache.commons.jxpath.ri.EvalContext;
021import org.apache.commons.jxpath.ri.QName;
022import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
023import org.apache.commons.jxpath.ri.compiler.NodeTest;
024import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
025import org.apache.commons.jxpath.ri.model.NodeIterator;
026import org.apache.commons.jxpath.ri.model.NodePointer;
027
028/**
029 * EvalContext that walks the "attribute::" axis.
030 *
031 * @author Dmitri Plotnikov
032 * @version $Revision: 652845 $ $Date: 2008-05-02 19:46:46 +0200 (Fr, 02 Mai 2008) $
033 */
034public class AttributeContext extends EvalContext {
035    private static final QName WILDCARD = new QName(null, "*");
036
037    private NodeTest nodeTest;
038    private boolean setStarted = false;
039    private NodeIterator iterator;
040    private NodePointer currentNodePointer;
041
042    /**
043     * Create a new AttributeContext.
044     * @param parentContext represents the previous step on the path
045     * @param nodeTest is the name of the attribute we are looking for
046     */
047    public AttributeContext(EvalContext parentContext, NodeTest nodeTest) {
048        super(parentContext);
049        this.nodeTest = nodeTest;
050    }
051
052    public NodePointer getCurrentNodePointer() {
053        return currentNodePointer;
054    }
055
056    public void reset() {
057        setStarted = false;
058        iterator = null;
059        super.reset();
060    }
061
062    public boolean setPosition(int position) {
063        if (position < getCurrentPosition()) {
064            reset();
065        }
066
067        while (getCurrentPosition() < position) {
068            if (!nextNode()) {
069                return false;
070            }
071        }
072        return true;
073    }
074
075    public boolean nextNode() {
076        super.setPosition(getCurrentPosition() + 1);
077        if (!setStarted) {
078            setStarted = true;
079            QName name;
080            if (nodeTest instanceof NodeNameTest) {
081                name = ((NodeNameTest) nodeTest).getNodeName();
082            }
083            else {
084                if (nodeTest instanceof NodeTypeTest
085                        && ((NodeTypeTest) nodeTest).getNodeType() == Compiler.NODE_TYPE_NODE) {
086                    name = WILDCARD;
087                }
088                else {
089                    iterator = null;
090                    return false;
091                }
092            }
093            iterator = parentContext.getCurrentNodePointer().attributeIterator(
094                    name);
095        }
096        if (iterator == null) {
097            return false;
098        }
099        if (!iterator.setPosition(iterator.getPosition() + 1)) {
100            return false;
101        }
102        currentNodePointer = iterator.getNodePointer();
103        return true;
104    }
105}