org.infinispan.schematic.internal.document.Paths Maven / Gradle / Ivy
/*
* ModeShape (http://www.modeshape.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.infinispan.schematic.internal.document;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import org.infinispan.commons.marshall.SerializeWith;
import org.infinispan.commons.util.Util;
import org.infinispan.schematic.document.Immutable;
import org.infinispan.schematic.document.Path;
import org.infinispan.schematic.internal.SchematicExternalizer;
import org.infinispan.schematic.internal.marshall.Ids;
public class Paths {
protected static final Path EMPTY_PATH = new EmptyPath();
protected static final void notNull( Object value,
String name ) {
if (value == null) throw new IllegalArgumentException("The '" + name + "' argument may not be null");
}
protected static final String notNull( String value,
String name ) {
if (value == null) throw new IllegalArgumentException("The '" + name + "' argument may not be null");
value = value.trim();
return value;
}
public static Path rootPath() {
return EMPTY_PATH;
}
public static Path path( String fieldName ) {
return new SinglePath(notNull(fieldName, "fieldName"));
}
public static Path path( String... fieldNames ) {
notNull(fieldNames, "fieldNames");
switch (fieldNames.length) {
case 0:
return EMPTY_PATH;
case 1:
return new SinglePath(fieldNames[0]);
default:
return new MultiSegmentPath(Arrays.asList(fieldNames));
}
}
public static Path path( List fieldNames ) {
notNull(fieldNames, "fieldNames");
switch (fieldNames.size()) {
case 0:
return EMPTY_PATH;
case 1:
return new SinglePath(fieldNames.get(0));
default:
// make copy so we're guaranteed to be immutable
return new MultiSegmentPath(new ArrayList(fieldNames));
}
}
public static Path path( Path path,
String fieldName ) {
notNull(path, "path");
return path.with(notNull(fieldName, "fieldName"));
}
public static Path path( Path path,
String... fieldNames ) {
notNull(path, "path");
notNull(fieldNames, "fieldNames");
if (fieldNames.length == 0) return path;
ArrayList names = new ArrayList(path.size() + fieldNames.length);
int i = 0;
for (String name : path) {
names.add(notNull(name, "fieldNames[" + i++ + "]"));
}
for (String name : fieldNames) {
names.add(notNull(name, "fieldNames[" + i++ + "]"));
}
return new MultiSegmentPath(names);
}
public static Path path( Path path,
List fieldNames ) {
notNull(path, "path");
notNull(fieldNames, "fieldNames");
if (fieldNames.isEmpty()) return path;
ArrayList names = new ArrayList(path.size() + fieldNames.size());
int i = 0;
for (String name : path) {
names.add(notNull(name, "fieldNames[" + i++ + "]"));
}
for (String name : fieldNames) {
names.add(notNull(name, "fieldNames[" + i++ + "]"));
}
return new MultiSegmentPath(names);
}
@Immutable
@SerializeWith( Paths.Externalizer.class )
protected static final class EmptyPath implements Path {
@Override
public Iterator iterator() {
return new Iterator() {
@Override
public boolean hasNext() {
return false;
}
@Override
public String next() {
throw new NoSuchElementException();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override
public String get( int index ) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: 0");
}
@Override
public String getLast() {
return null;
}
@Override
public String getFirst() {
return null;
}
@Override
public int size() {
return 0;
}
@Override
public boolean startsWith( Path ancestor ) {
return ancestor.size() == 0;
}
@Override
public Path with( String fieldName ) {
return fieldName != null ? new SinglePath(notNull(fieldName, "fieldName")) : this;
}
@Override
public Path parent() {
return EMPTY_PATH;
}
@Override
public int compareTo( Path that ) {
if (that == this) return 0;
if (that instanceof EmptyPath) return 0;
return 0 - that.size();
}
@Override
public int hashCode() {
return 1;
}
@Override
public boolean equals( Object obj ) {
if (obj == this) return true;
if (obj instanceof Path) {
Path that = (Path)obj;
return that.size() == 0;
}
return false;
}
@Override
public String toString() {
return "";
}
}
@Immutable
@SerializeWith( Paths.Externalizer.class )
protected static final class SinglePath implements Path {
private final String fieldName;
protected SinglePath( String fieldName ) {
this.fieldName = fieldName;
}
@Override
public Iterator iterator() {
return new Iterator() {
private boolean done = false;
@Override
public boolean hasNext() {
return !done;
}
@SuppressWarnings( "synthetic-access" )
@Override
public String next() {
done = true;
return fieldName;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override
public String get( int index ) {
if (index != 0) throw new IndexOutOfBoundsException("Index: " + index + ", Size: 1");
return fieldName;
}
@Override
public String getLast() {
return fieldName;
}
@Override
public String getFirst() {
return fieldName;
}
@Override
public Path with( String fieldName ) {
return Paths.path(this.fieldName, fieldName);
}
@Override
public Path parent() {
return EMPTY_PATH;
}
@Override
public int size() {
return 1;
}
@Override
public int hashCode() {
return fieldName.hashCode();
}
@Override
public int compareTo( Path that ) {
if (that == this) return 0;
int diff = this.size() - that.size();
if (diff != 0) return diff;
return this.fieldName.compareTo(that.get(0));
}
@Override
public boolean startsWith( Path ancestor ) {
return this.equals(ancestor);
}
@Override
public boolean equals( Object obj ) {
if (obj == this) return true;
if (obj instanceof SinglePath) {
SinglePath that = (SinglePath)obj;
return this.fieldName.equals(that.fieldName);
}
if (obj instanceof Path) {
Path that = (Path)obj;
if (this.size() != that.size()) return false;
return this.fieldName.equals(that.get(0));
}
return false;
}
@Override
public String toString() {
return fieldName;
}
}
@Immutable
@SerializeWith( Paths.Externalizer.class )
protected static final class MultiSegmentPath implements Path {
private final List fieldNames;
private transient String composite;
protected MultiSegmentPath( List fieldNames ) {
assert fieldNames != null;
assert !fieldNames.isEmpty();
this.fieldNames = fieldNames;
}
@Override
public Iterator iterator() {
final Iterator actualIter = fieldNames.iterator();
return new Iterator() {
@Override
public boolean hasNext() {
return actualIter.hasNext();
}
@Override
public String next() {
return actualIter.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override
public String get( int index ) {
return fieldNames.get(index);
}
@Override
public String getLast() {
return fieldNames.get(fieldNames.size() - 1);
}
@Override
public String getFirst() {
return fieldNames.get(0);
}
@Override
public int size() {
return fieldNames.size();
}
@Override
public boolean startsWith( Path other ) {
if (other.size() > this.size()) return false;
Iterator thatIter = other.iterator();
Iterator thisIter = this.iterator();
while (thatIter.hasNext() && thisIter.hasNext()) {
if (!thisIter.next().equals(thatIter.next())) return false;
}
return !thatIter.hasNext();
}
@Override
public Path with( String fieldName ) {
fieldName = notNull(fieldName, "fieldName");
List newFieldNames = new ArrayList(fieldNames.size() + 1);
newFieldNames.addAll(this.fieldNames);
newFieldNames.add(fieldName);
return new MultiSegmentPath(newFieldNames);
}
@Override
public Path parent() {
if (size() <= 1) return EMPTY_PATH;
List parentFieldNames = this.fieldNames.subList(0, this.fieldNames.size() - 1);
return new MultiSegmentPath(parentFieldNames);
}
@Override
public int hashCode() {
return fieldNames.hashCode();
}
@Override
public int compareTo( Path that ) {
if (that == this) return 0;
int diff = this.size() - that.size();
if (diff != 0) return diff;
Iterator thatIter = that.iterator();
Iterator thisIter = this.iterator();
while (thatIter.hasNext()) {
int value = thisIter.next().compareTo(thatIter.next());
if (value != 0) return value;
}
assert !thisIter.hasNext();
return 0;
}
@Override
public boolean equals( Object obj ) {
if (obj == this) return true;
if (obj instanceof Path) {
Path that = (Path)obj;
if (this.size() != that.size()) return false;
Iterator thatIter = that.iterator();
Iterator thisIter = this.iterator();
while (thatIter.hasNext()) {
if (!thisIter.next().equals(thatIter.next())) return false;
}
assert !thisIter.hasNext();
return true;
}
return false;
}
@Override
public String toString() {
if (composite == null) {
StringBuilder sb = new StringBuilder();
Iterator iter = fieldNames.iterator();
if (iter.hasNext()) {
sb.append(iter.next());
while (iter.hasNext()) {
sb.append('.');
sb.append(iter.next());
}
}
composite = sb.toString();
}
return composite;
}
}
public static class Externalizer extends SchematicExternalizer {
private static final long serialVersionUID = 1L;
@Override
public void writeObject( ObjectOutput output,
Path path ) throws IOException {
output.writeInt(path.size());
for (String fieldName : path) {
output.writeUTF(fieldName);
}
}
@Override
public Path readObject( ObjectInput input ) throws IOException {
int number = input.readInt();
if (number == 0) {
return Paths.rootPath();
}
if (number == 1) {
String fieldName = input.readUTF();
return Paths.path(fieldName);
}
List fieldNames = new ArrayList(number);
for (int i = 0; i != number; ++i) {
fieldNames.add(input.readUTF());
}
return Paths.path(fieldNames);
}
@Override
public Integer getId() {
return Ids.SCHEMATIC_VALUE_PATH;
}
@SuppressWarnings( "unchecked" )
@Override
public Set> getTypeClasses() {
return Util.asSet(EmptyPath.class, SinglePath.class, MultiSegmentPath.class);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy