001    /*
002     * JBoss DNA (http://www.jboss.org/dna)
003     * See the COPYRIGHT.txt file distributed with this work for information
004     * regarding copyright ownership.  Some portions may be licensed
005     * to Red Hat, Inc. under one or more contributor license agreements.
006     * See the AUTHORS.txt file in the distribution for a full listing of 
007     * individual contributors. 
008     *
009     * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
010     * is licensed to you under the terms of the GNU Lesser General Public License as
011     * published by the Free Software Foundation; either version 2.1 of
012     * the License, or (at your option) any later version.
013     *
014     * JBoss DNA is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
016     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017     * Lesser General Public License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this software; if not, write to the Free
021     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
022     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
023     */
024    package org.jboss.dna.graph.property.basic;
025    
026    import net.jcip.annotations.Immutable;
027    import org.jboss.dna.common.text.TextEncoder;
028    import org.jboss.dna.graph.property.Name;
029    import org.jboss.dna.graph.property.NamespaceRegistry;
030    import org.jboss.dna.graph.property.Path;
031    
032    /**
033     * A basic implementation of {@link Path.Segment}.
034     * 
035     * @author Randall Hauch
036     */
037    @Immutable
038    public class BasicPathSegment implements Path.Segment {
039    
040        /**
041         */
042        private static final long serialVersionUID = 4367349287846075157L;
043        private final Name name;
044        private final int index;
045    
046        /**
047         * @param name the segment name
048         * @throws IllegalArgumentException if the name is null or if the index is invalid
049         */
050        public BasicPathSegment( Name name ) {
051            assert name != null;
052            this.name = name;
053            this.index = Path.DEFAULT_INDEX;
054        }
055    
056        /**
057         * @param name the segment name
058         * @param index the segment index
059         * @throws IllegalArgumentException if the name is null or if the index is invalid
060         */
061        public BasicPathSegment( Name name,
062                                 int index ) {
063            assert name != null;
064            assert index >= Path.DEFAULT_INDEX;
065            this.name = name;
066            this.index = (this.isSelfReference() || this.isParentReference()) ? Path.DEFAULT_INDEX : index;
067        }
068    
069        /**
070         * {@inheritDoc}
071         */
072        public int getIndex() {
073            return this.index;
074        }
075    
076        /**
077         * {@inheritDoc}
078         */
079        public Name getName() {
080            return this.name;
081        }
082    
083        /**
084         * {@inheritDoc}
085         */
086        public boolean hasIndex() {
087            return this.index != Path.DEFAULT_INDEX;
088        }
089    
090        /**
091         * {@inheritDoc}
092         */
093        public boolean isParentReference() {
094            return this.name.getLocalName().equals(Path.PARENT) && this.name.getNamespaceUri().length() == 0;
095        }
096    
097        /**
098         * {@inheritDoc}
099         */
100        public boolean isSelfReference() {
101            return this.name.getLocalName().equals(Path.SELF) && this.name.getNamespaceUri().length() == 0;
102        }
103    
104        /**
105         * {@inheritDoc}
106         */
107        public int compareTo( Path.Segment that ) {
108            if (this == that) return 0;
109            int diff = this.getName().compareTo(that.getName());
110            if (diff != 0) return diff;
111            return this.getIndex() - that.getIndex();
112        }
113    
114        /**
115         * {@inheritDoc}
116         */
117        @Override
118        public int hashCode() {
119            return this.name.hashCode();
120        }
121    
122        /**
123         * {@inheritDoc}
124         */
125        @Override
126        public boolean equals( Object obj ) {
127            if (obj == this) return true;
128            if (obj instanceof Path.Segment) {
129                Path.Segment that = (Path.Segment)obj;
130                if (!this.getName().equals(that.getName())) return false;
131                return Math.abs(getIndex()) == Math.abs(that.getIndex());
132            }
133            return false;
134        }
135    
136        /**
137         * {@inheritDoc}
138         */
139        @Override
140        public String toString() {
141            if (this.hasIndex()) {
142                return this.getName().toString() + "[" + this.getIndex() + "]";
143            }
144            return this.getName().toString();
145        }
146    
147        /**
148         * {@inheritDoc}
149         */
150        public String getUnencodedString() {
151            return getString(Path.NO_OP_ENCODER);
152        }
153    
154        /**
155         * {@inheritDoc}
156         */
157        public String getString() {
158            return getString(Path.DEFAULT_ENCODER);
159        }
160    
161        /**
162         * {@inheritDoc}
163         */
164        public String getString( TextEncoder encoder ) {
165            if (encoder == null) encoder = Path.DEFAULT_ENCODER;
166            String encodedName = this.getName().getString(encoder);
167            if (this.hasIndex()) {
168                return encodedName + "[" + this.getIndex() + "]";
169            }
170            return encodedName;
171        }
172    
173        /**
174         * {@inheritDoc}
175         */
176        public String getString( NamespaceRegistry namespaceRegistry ) {
177            return getString(namespaceRegistry, Path.DEFAULT_ENCODER);
178        }
179    
180        /**
181         * {@inheritDoc}
182         */
183        public String getString( NamespaceRegistry namespaceRegistry,
184                                 TextEncoder encoder ) {
185            return getString(namespaceRegistry, encoder, null);
186        }
187    
188        /**
189         * {@inheritDoc}
190         * 
191         * @see org.jboss.dna.graph.property.Path.Segment#getString(org.jboss.dna.graph.property.NamespaceRegistry,
192         *      org.jboss.dna.common.text.TextEncoder, org.jboss.dna.common.text.TextEncoder)
193         */
194        public String getString( NamespaceRegistry namespaceRegistry,
195                                 TextEncoder encoder,
196                                 TextEncoder delimiterEncoder ) {
197            if (encoder == null) encoder = Path.DEFAULT_ENCODER;
198            String encodedName = this.getName().getString(namespaceRegistry, encoder, delimiterEncoder);
199            if (this.hasIndex()) {
200                return encodedName + "[" + this.getIndex() + "]";
201            }
202            return encodedName;
203        }
204    }