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 java.util.Collections;
027 import java.util.Iterator;
028 import java.util.List;
029 import net.jcip.annotations.Immutable;
030 import org.jboss.dna.common.text.Inflector;
031 import org.jboss.dna.common.util.CheckArg;
032 import org.jboss.dna.graph.GraphI18n;
033 import org.jboss.dna.graph.property.InvalidPathException;
034 import org.jboss.dna.graph.property.Path;
035
036 /**
037 * A basic implementation of {@link Path}.
038 *
039 * @author Randall Hauch
040 * @author John Verhaeg
041 */
042 @Immutable
043 public class BasicPath extends AbstractPath {
044
045 /**
046 * The initial serializable version. Version {@value}
047 */
048 private static final long serialVersionUID = 1L;
049
050 private static final List<Segment> EMPTY_SEGMENTS = Collections.emptyList();
051
052 public static final Path EMPTY_RELATIVE = new BasicPath(EMPTY_SEGMENTS, false);
053
054 public static final Path SELF_PATH = new BasicPath(Collections.singletonList(Path.SELF_SEGMENT), false);
055
056 public static final Path PARENT_PATH = new BasicPath(Collections.singletonList(Path.PARENT_SEGMENT), false);
057
058 private final List<Segment> segments;
059 private final boolean absolute;
060 private final boolean normalized;
061
062 /**
063 * @param segments the segments
064 * @param absolute true if this path is absolute, or false otherwise
065 */
066 public BasicPath( List<Segment> segments,
067 boolean absolute ) {
068 assert segments != null;
069 this.segments = Collections.unmodifiableList(segments);
070 this.absolute = absolute;
071 this.normalized = isNormalized(this.segments);
072 }
073
074 /**
075 * {@inheritDoc}
076 */
077 public Path getAncestor( int degree ) {
078 CheckArg.isNonNegative(degree, "degree");
079 if (degree == 0) return this;
080 int endIndex = this.segments.size() - degree;
081 if (endIndex == 0) return this.isAbsolute() ? RootPath.INSTANCE : null;
082 if (endIndex < 0) {
083 String msg = GraphI18n.pathAncestorDegreeIsInvalid.text(this.getString(), Inflector.getInstance().ordinalize(degree));
084 throw new InvalidPathException(msg);
085 }
086 return subpath(0, endIndex);
087 }
088
089 /**
090 * {@inheritDoc}
091 *
092 * @see org.jboss.dna.graph.property.basic.AbstractPath#getSegmentsOfParent()
093 */
094 @Override
095 protected Iterator<Segment> getSegmentsOfParent() {
096 int size = this.segments.size();
097 if (size == 1) return EMPTY_PATH_ITERATOR;
098 return this.segments.subList(0, size - 1).iterator();
099 }
100
101 /**
102 * {@inheritDoc}
103 */
104 public List<Segment> getSegmentsList() {
105 return this.segments;
106 }
107
108 /**
109 * {@inheritDoc}
110 */
111 public boolean isAbsolute() {
112 return this.absolute;
113 }
114
115 /**
116 * {@inheritDoc}
117 */
118 public boolean isNormalized() {
119 return this.normalized;
120 }
121
122 /**
123 * {@inheritDoc}
124 */
125 public boolean isRoot() {
126 return false;
127 }
128
129 /**
130 * {@inheritDoc}
131 */
132 public int size() {
133 return this.segments.size();
134 }
135
136 }