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