ReaderDepthState.java
/*
* Copyright (C) 2006 Joe Walnes.
* Copyright (C) 2006, 2007, 2014, 2015, 2018 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
* style license a copy of which has been included with this distribution in
* the LICENSE.txt file.
*
* Created on 04. June 2006 by Joe Walnes
*/
package com.thoughtworks.xstream.io.binary;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* Maintains the state of a pull reader at various states in the document depth. Used by the {@link BinaryStreamReader}
*
* @author Joe Walnes
* @since 1.2
*/
class ReaderDepthState {
private static final String EMPTY_STRING = "";
private static class State {
String name;
String value;
List<Attribute> attributes;
boolean hasMoreChildren;
State parent;
int level;
}
private static class Attribute {
String name;
String value;
}
private State current;
public void push() {
final State newState = new State();
newState.parent = current;
newState.level = getLevel() + 1;
current = newState;
}
public void pop() {
current = current.parent;
}
public int getLevel() {
return current != null ? current.level : 0;
}
public String getName() {
return current.name;
}
public void setName(final String name) {
current.name = name;
}
public String getValue() {
return current.value == null ? EMPTY_STRING : current.value;
}
public void setValue(final String value) {
current.value = value;
}
public boolean hasMoreChildren() {
return current.hasMoreChildren;
}
public void setHasMoreChildren(final boolean hasMoreChildren) {
current.hasMoreChildren = hasMoreChildren;
}
public void addAttribute(final String name, final String value) {
final Attribute attribute = new Attribute();
attribute.name = name;
attribute.value = value;
if (current.attributes == null) {
current.attributes = new ArrayList<>();
}
current.attributes.add(attribute);
}
public String getAttribute(final String name) {
if (current.attributes == null) {
return null;
} else {
// For short maps, it's faster to iterate then do a hashlookup.
for (final Attribute attribute : current.attributes) {
if (attribute.name.equals(name)) {
return attribute.value;
}
}
return null;
}
}
public String getAttribute(final int index) {
if (current.attributes == null) {
return null;
} else {
final Attribute attribute = current.attributes.get(index);
return attribute.value;
}
}
public String getAttributeName(final int index) {
if (current.attributes == null) {
return null;
} else {
final Attribute attribute = current.attributes.get(index);
return attribute.name;
}
}
public int getAttributeCount() {
return current.attributes == null ? 0 : current.attributes.size();
}
public Iterator<String> getAttributeNames() {
if (current.attributes == null) {
return Collections.<String>emptyIterator();
} else {
final Iterator<Attribute> attributeIterator = current.attributes.iterator();
return new Iterator<String>() {
@Override
public boolean hasNext() {
return attributeIterator.hasNext();
}
@Override
public String next() {
final Attribute attribute = attributeIterator.next();
return attribute.name;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
}