Impl to it.
*/
public static final AttributeFactory DEFAULT_ATTRIBUTE_FACTORY = new DefaultAttributeFactory();
private static final class DefaultAttributeFactory extends AttributeFactory {
private static final IdentityHashMapPlease note: It is not guaranteed, that att is added to
* the AttributeSource, because the provided attributes may already exist.
* You should always retrieve the wanted attributes using {@link #getAttribute} after adding
* with this method and cast to your class.
* The recommended way to use custom implementations is using an {@link AttributeFactory}.
*
* Note that this method does not affect attributes of the targetStream
* that are not contained in this state. In other words, if for example
* the targetStream contains an OffsetAttribute, but this state doesn't, then
* the value of the OffsetAttribute remains unchanged. It might be desirable to
* reset its value to the default, in which case the caller should first
* call {@link TokenStream#clearAttributes()} on the targetStream.
*/
public void restoreState(State state) {
if (state == null) return;
do {
AttributeImpl targetImpl = attributeImpls.get(state.attribute.getClass());
if (targetImpl == null)
throw new IllegalArgumentException("State contains an AttributeImpl that is not in this AttributeSource");
state.attribute.copyTo(targetImpl);
state = state.next;
} while (state != null);
}
@Override
public int hashCode() {
int code = 0;
if (hasAttributes()) {
if (currentState == null) {
computeCurrentState();
}
for (State state = currentState; state != null; state = state.next) {
code = code * 31 + state.attribute.hashCode();
}
}
return code;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof AttributeSource) {
AttributeSource other = (AttributeSource) obj;
if (hasAttributes()) {
if (!other.hasAttributes()) {
return false;
}
if (this.attributeImpls.size() != other.attributeImpls.size()) {
return false;
}
// it is only equal if all attribute impls are the same in the same order
if (this.currentState == null) {
this.computeCurrentState();
}
State thisState = this.currentState;
if (other.currentState == null) {
other.computeCurrentState();
}
State otherState = other.currentState;
while (thisState != null && otherState != null) {
if (otherState.attribute.getClass() != thisState.attribute.getClass() || !otherState.attribute.equals(thisState.attribute)) {
return false;
}
thisState = thisState.next;
otherState = otherState.next;
}
return true;
} else {
return !other.hasAttributes();
}
} else
return false;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder().append('(');
if (hasAttributes()) {
if (currentState == null) {
computeCurrentState();
}
for (State state = currentState; state != null; state = state.next) {
if (state != currentState) sb.append(',');
sb.append(state.attribute.toString());
}
}
return sb.append(')').toString();
}
/**
* Performs a clone of all {@link AttributeImpl} instances returned in a new
* AttributeSource instance. This method can be used to e.g. create another TokenStream
* with exactly the same attributes (using {@link #AttributeSource(AttributeSource)})
*/
public AttributeSource cloneAttributes() {
AttributeSource clone = new AttributeSource(this.factory);
// first clone the impls
if (hasAttributes()) {
if (currentState == null) {
computeCurrentState();
}
for (State state = currentState; state != null; state = state.next) {
clone.attributeImpls.put(state.attribute.getClass(), (AttributeImpl) state.attribute.clone());
}
}
// now the interfaces
for (Entry