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 }