package org.apache.lucene.util;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.tokenattributes.*;
import java.util.Iterator;
import java.util.HashMap;
import java.util.Map;
public class TestAttributeSource extends LuceneTestCase {
public void testCaptureState() {
// init a first instance
AttributeSource src = new AttributeSource();
CharTermAttribute termAtt = src.addAttribute(CharTermAttribute.class);
TypeAttribute typeAtt = src.addAttribute(TypeAttribute.class);
termAtt.append("TestTerm");
typeAtt.setType("TestType");
final int hashCode = src.hashCode();
AttributeSource.State state = src.captureState();
// modify the attributes
termAtt.setEmpty().append("AnotherTestTerm");
typeAtt.setType("AnotherTestType");
assertTrue("Hash code should be different", hashCode != src.hashCode());
src.restoreState(state);
assertEquals("TestTerm", termAtt.toString());
assertEquals("TestType", typeAtt.type());
assertEquals("Hash code should be equal after restore", hashCode, src.hashCode());
// restore into an exact configured copy
AttributeSource copy = new AttributeSource();
copy.addAttribute(CharTermAttribute.class);
copy.addAttribute(TypeAttribute.class);
copy.restoreState(state);
assertEquals("Both AttributeSources should have same hashCode after restore", src.hashCode(), copy.hashCode());
assertEquals("Both AttributeSources should be equal after restore", src, copy);
// init a second instance (with attributes in different order and one additional attribute)
AttributeSource src2 = new AttributeSource();
typeAtt = src2.addAttribute(TypeAttribute.class);
FlagsAttribute flagsAtt = src2.addAttribute(FlagsAttribute.class);
termAtt = src2.addAttribute(CharTermAttribute.class);
flagsAtt.setFlags(12345);
src2.restoreState(state);
assertEquals("TestTerm", termAtt.toString());
assertEquals("TestType", typeAtt.type());
assertEquals("FlagsAttribute should not be touched", 12345, flagsAtt.getFlags());
// init a third instance missing one Attribute
AttributeSource src3 = new AttributeSource();
termAtt = src3.addAttribute(CharTermAttribute.class);
try {
src3.restoreState(state);
fail("The third instance is missing the TypeAttribute, so restoreState() should throw IllegalArgumentException");
} catch (IllegalArgumentException iae) {
// pass
}
}
public void testCloneAttributes() {
final AttributeSource src = new AttributeSource();
final FlagsAttribute flagsAtt = src.addAttribute(FlagsAttribute.class);
final TypeAttribute typeAtt = src.addAttribute(TypeAttribute.class);
flagsAtt.setFlags(1234);
typeAtt.setType("TestType");
final AttributeSource clone = src.cloneAttributes();
final Iterator<Class<? extends Attribute>> it = clone.getAttributeClassesIterator();
assertEquals("FlagsAttribute must be the first attribute", FlagsAttribute.class, it.next());
assertEquals("TypeAttribute must be the second attribute", TypeAttribute.class, it.next());
assertFalse("No more attributes", it.hasNext());
final FlagsAttribute flagsAtt2 = clone.getAttribute(FlagsAttribute.class);
final TypeAttribute typeAtt2 = clone.getAttribute(TypeAttribute.class);
assertNotSame("FlagsAttribute of original and clone must be different instances", flagsAtt2, flagsAtt);
assertNotSame("TypeAttribute of original and clone must be different instances", typeAtt2, typeAtt);
assertEquals("FlagsAttribute of original and clone must be equal", flagsAtt2, flagsAtt);
assertEquals("TypeAttribute of original and clone must be equal", typeAtt2, typeAtt);
// test copy back
flagsAtt2.setFlags(4711);
typeAtt2.setType("OtherType");
clone.copyTo(src);
assertEquals("FlagsAttribute of original must now contain updated term", 4711, flagsAtt.getFlags());
assertEquals("TypeAttribute of original must now contain updated type", "OtherType", typeAtt.type());
// verify again:
assertNotSame("FlagsAttribute of original and clone must be different instances", flagsAtt2, flagsAtt);
assertNotSame("TypeAttribute of original and clone must be different instances", typeAtt2, typeAtt);
assertEquals("FlagsAttribute of original and clone must be equal", flagsAtt2, flagsAtt);
assertEquals("TypeAttribute of original and clone must be equal", typeAtt2, typeAtt);
}
public void testToStringAndMultiAttributeImplementations() {
AttributeSource src = new AttributeSource();
CharTermAttribute termAtt = src.addAttribute(CharTermAttribute.class);
TypeAttribute typeAtt = src.addAttribute(TypeAttribute.class);
termAtt.append("TestTerm");
typeAtt.setType("TestType");
assertEquals("Attributes should appear in original order", "("+termAtt.toString()+","+typeAtt.toString()+")", src.toString());
Iterator<AttributeImpl> it = src.getAttributeImplsIterator();
assertTrue("Iterator should have 2 attributes left", it.hasNext());
assertSame("First AttributeImpl from iterator should be termAtt", termAtt, it.next());
assertTrue("Iterator should have 1 attributes left", it.hasNext());
assertSame("Second AttributeImpl from iterator should be typeAtt", typeAtt, it.next());
assertFalse("Iterator should have 0 attributes left", it.hasNext());
src = new AttributeSource();
src.addAttributeImpl(new Token());
// this should not add a new attribute as Token implements CharTermAttribute, too
termAtt = src.addAttribute(CharTermAttribute.class);
assertTrue("CharTermAttribute should be implemented by Token", termAtt instanceof Token);
// get the Token attribute and check, that it is the only one
it = src.getAttributeImplsIterator();
Token tok = (Token) it.next();
assertFalse("There should be only one attribute implementation instance", it.hasNext());
termAtt.setEmpty().append("TestTerm");
assertEquals("Token should only printed once", "("+tok.toString()+")", src.toString());
}
public void testDefaultAttributeFactory() throws Exception {
AttributeSource src = new AttributeSource();
assertTrue("CharTermAttribute is not implemented by CharTermAttributeImpl",
src.addAttribute(CharTermAttribute.class) instanceof CharTermAttributeImpl);
assertTrue("OffsetAttribute is not implemented by OffsetAttributeImpl",
src.addAttribute(OffsetAttribute.class) instanceof OffsetAttributeImpl);
assertTrue("FlagsAttribute is not implemented by FlagsAttributeImpl",
src.addAttribute(FlagsAttribute.class) instanceof FlagsAttributeImpl);
assertTrue("PayloadAttribute is not implemented by PayloadAttributeImpl",
src.addAttribute(PayloadAttribute.class) instanceof PayloadAttributeImpl);
assertTrue("PositionIncrementAttribute is not implemented by PositionIncrementAttributeImpl",
src.addAttribute(PositionIncrementAttribute.class) instanceof PositionIncrementAttributeImpl);
assertTrue("TypeAttribute is not implemented by TypeAttributeImpl",
src.addAttribute(TypeAttribute.class) instanceof TypeAttributeImpl);
}
@SuppressWarnings("unchecked")
public void testInvalidArguments() throws Exception {
try {
AttributeSource src = new AttributeSource();
src.addAttribute(Token.class);
fail("Should throw IllegalArgumentException");
} catch (IllegalArgumentException iae) {}
try {
AttributeSource src = new AttributeSource(Token.TOKEN_ATTRIBUTE_FACTORY);
src.addAttribute(Token.class);
fail("Should throw IllegalArgumentException");
} catch (IllegalArgumentException iae) {}
try {
AttributeSource src = new AttributeSource();
// break this by unsafe cast
src.addAttribute((Class) Iterator.class);
fail("Should throw IllegalArgumentException");
} catch (IllegalArgumentException iae) {}
}
public void testLUCENE_3042() throws Exception {
final AttributeSource src1 = new AttributeSource();
src1.addAttribute(CharTermAttribute.class).append("foo");
int hash1 = src1.hashCode(); // this triggers a cached state
final AttributeSource src2 = new AttributeSource(src1);
src2.addAttribute(TypeAttribute.class).setType("bar");
assertTrue("The hashCode is identical, so the captured state was preserved.", hash1 != src1.hashCode());
assertEquals(src2.hashCode(), src1.hashCode());
}
// this class is included in external class check, so no assertion errors occur
@Deprecated
static class TestAttributeImpl extends AttributeImpl implements FlagsAttribute {
private int flags = 0;
public int getFlags() { return flags; }
public void setFlags(int flags) { this.flags = flags; }
@Override
public void clear() { flags = 0; }
@Override
public void copyTo(AttributeImpl target) {
FlagsAttribute t = (FlagsAttribute) target;
t.setFlags(flags);
}
@Override
public String toString() {
return "foo=bar,moo=mae";
}
}
// this class is excluded in external class check, so assertion on calling reflectWith should occur
@Deprecated
static class TestAttributeImpl2 extends TestAttributeImpl {}
@Deprecated
public void testReflectionOfToString() throws Exception {
final AttributeSource src = new AttributeSource();
final AttributeImpl att = new TestAttributeImpl();
src.addAttributeImpl(att);
assertSame("FlagsAttribute is not implemented by same instance of TestAttributeImpl",
att, src.addAttribute(FlagsAttribute.class));
final Map<String,Object> map = new HashMap<String,Object>();
final AttributeReflector reflector = new AttributeReflector() {
public void reflect(Class<? extends Attribute> attClass, String key, Object value) {
assertSame(FlagsAttribute.class, attClass);
map.put(key, value);
}
};
att.reflectWith(reflector);
assertEquals(2, map.size());
assertEquals("bar", map.get("foo"));
assertEquals("mae", map.get("moo"));
map.clear();
src.reflectWith(reflector);
assertEquals(2, map.size());
assertEquals("bar", map.get("foo"));
assertEquals("mae", map.get("moo"));
map.clear();
try {
new TestAttributeImpl2().reflectWith(reflector);
fail("TestAttributeImpl2 should fail assertion on toString() parsing");
} catch (AssertionError e) {
// pass
}
}
}