LUCENE-6651: AttributeImpl#reflectWith(AttributeReflector) was made abstract and has no reflection-based default implementation anymore.

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1688855 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Uwe Schindler 2015-07-02 16:18:51 +00:00
parent 1816ed1945
commit 4accc25477
23 changed files with 146 additions and 45 deletions

View File

@ -42,6 +42,9 @@ API Changes
BooleanQuery with one MUST clause for the query, and one FILTER clause for
the filter. (Adrien Grand)
* LUCENE-6651: AttributeImpl#reflectWith(AttributeReflector) was made
abstract and has no reflection-based default implementation anymore.
(Uwe Schindler)
======================= Lucene 5.3.0 =======================
@ -262,6 +265,11 @@ Changes in Runtime Behavior
* LUCENE-6542: FSDirectory's ctor now works with security policies or file systems
that restrict write access. (Trejkaz, hossman, Uwe Schindler)
* LUCENE-6651: The default implementation of AttributeImpl#reflectWith(AttributeReflector)
now uses AccessControler#doPrivileged() to do the reflection. Please consider
implementing this method in all your custom attributes, because the method will be
made abstract in Lucene 6. (Uwe Schindler)
Optimizations
* LUCENE-6548: Some optimizations for BlockTree's intersect with very

View File

@ -40,3 +40,9 @@ can now be constructed this way using its builder:
.setMinimumNumberShouldMatch(1)
.build();
## AttributeImpl now requires that reflectWith() is implemented (LUCENE-6651)
AttributeImpl removed the default, reflection-based implementation of
reflectWith(AtrributeReflector). The method was made abstract. If you have
implemented your own attribute, make sure to add the required method sigature.
See the Javadocs for an example.

View File

@ -36,6 +36,7 @@ import org.apache.lucene.analysis.util.CharArraySet;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.util.Attribute;
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
import org.xml.sax.InputSource;
public class TestCompoundWordTokenFilter extends BaseTokenStreamTestCase {
@ -269,23 +270,32 @@ public class TestCompoundWordTokenFilter extends BaseTokenStreamTestCase {
public static final class MockRetainAttributeImpl extends AttributeImpl implements MockRetainAttribute {
private boolean retain = false;
@Override
public void clear() {
retain = false;
}
@Override
public boolean getRetain() {
return retain;
}
@Override
public void setRetain(boolean retain) {
this.retain = retain;
}
@Override
public void copyTo(AttributeImpl target) {
MockRetainAttribute t = (MockRetainAttribute) target;
t.setRetain(retain);
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(MockRetainAttribute.class, "retain", retain);
}
}
private static class MockRetainAttributeFilter extends TokenFilter {

View File

@ -21,6 +21,7 @@ package org.apache.lucene.analysis.morfologik;
import java.util.*;
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
/**
* Morphosyntactic annotations for surface forms.
@ -96,4 +97,9 @@ public class MorphosyntacticTagsAttributeImpl extends AttributeImpl
this.copyTo(cloned);
return cloned;
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(MorphosyntacticTagsAttribute.class, "tags", tags);
}
}

View File

@ -18,6 +18,7 @@ package org.apache.lucene.analysis.tokenattributes;
*/
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
/** Default implementation of {@link FlagsAttribute}. */
public class FlagsAttributeImpl extends AttributeImpl implements FlagsAttribute, Cloneable {
@ -64,4 +65,9 @@ public class FlagsAttributeImpl extends AttributeImpl implements FlagsAttribute,
FlagsAttribute t = (FlagsAttribute) target;
t.setFlags(flags);
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(FlagsAttribute.class, "flags", flags);
}
}

View File

@ -18,6 +18,7 @@ package org.apache.lucene.analysis.tokenattributes;
*/
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
/** Default implementation of {@link KeywordAttribute}. */
public final class KeywordAttributeImpl extends AttributeImpl implements
@ -63,4 +64,8 @@ public final class KeywordAttributeImpl extends AttributeImpl implements
keyword = isKeyword;
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(KeywordAttribute.class, "keyword", keyword);
}
}

View File

@ -18,6 +18,7 @@ package org.apache.lucene.analysis.tokenattributes;
*/
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
/** Default implementation of {@link OffsetAttribute}. */
public class OffsetAttributeImpl extends AttributeImpl implements OffsetAttribute, Cloneable {
@ -90,4 +91,10 @@ public class OffsetAttributeImpl extends AttributeImpl implements OffsetAttribut
OffsetAttribute t = (OffsetAttribute) target;
t.setOffset(startOffset, endOffset);
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(OffsetAttribute.class, "startOffset", startOffset);
reflector.reflect(OffsetAttribute.class, "endOffset", endOffset);
}
}

View File

@ -18,6 +18,7 @@ package org.apache.lucene.analysis.tokenattributes;
*/
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
import org.apache.lucene.util.BytesRef;
/** Default implementation of {@link PayloadAttribute}. */
@ -89,5 +90,8 @@ public class PayloadAttributeImpl extends AttributeImpl implements PayloadAttrib
t.setPayload((payload == null) ? null : BytesRef.deepCopyOf(payload));
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(PayloadAttribute.class, "payload", payload);
}
}

View File

@ -18,6 +18,7 @@ package org.apache.lucene.analysis.tokenattributes;
*/
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
/** Default implementation of {@link PositionIncrementAttribute}. */
public class PositionIncrementAttributeImpl extends AttributeImpl implements PositionIncrementAttribute, Cloneable {
@ -69,4 +70,9 @@ public class PositionIncrementAttributeImpl extends AttributeImpl implements Pos
PositionIncrementAttribute t = (PositionIncrementAttribute) target;
t.setPositionIncrement(positionIncrement);
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(PositionIncrementAttribute.class, "positionIncrement", positionIncrement);
}
}

View File

@ -18,6 +18,7 @@ package org.apache.lucene.analysis.tokenattributes;
*/
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
/** Default implementation of {@link PositionLengthAttribute}. */
public class PositionLengthAttributeImpl extends AttributeImpl implements PositionLengthAttribute, Cloneable {
@ -69,4 +70,9 @@ public class PositionLengthAttributeImpl extends AttributeImpl implements Positi
PositionLengthAttribute t = (PositionLengthAttribute) target;
t.setPositionLength(positionLength);
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(PositionLengthAttribute.class, "positionLength", positionLength);
}
}

View File

@ -18,6 +18,7 @@ package org.apache.lucene.analysis.tokenattributes;
*/
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
/** Default implementation of {@link TypeAttribute}. */
public class TypeAttributeImpl extends AttributeImpl implements TypeAttribute, Cloneable {
@ -72,4 +73,9 @@ public class TypeAttributeImpl extends AttributeImpl implements TypeAttribute, C
TypeAttribute t = (TypeAttribute) target;
t.setType(type);
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(TypeAttribute.class, "type", type);
}
}

View File

@ -18,6 +18,7 @@ package org.apache.lucene.search;
*/
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
/** Implementation class for {@link BoostAttribute}.
* @lucene.internal
@ -44,4 +45,9 @@ public final class BoostAttributeImpl extends AttributeImpl implements BoostAttr
public void copyTo(AttributeImpl target) {
((BoostAttribute) target).setBoost(boost);
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(BoostAttribute.class, "boost", boost);
}
}

View File

@ -30,6 +30,7 @@ import org.apache.lucene.index.Terms;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.util.Attribute;
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
import org.apache.lucene.util.AttributeSource;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.BytesRefBuilder;
@ -424,5 +425,10 @@ public class FuzzyTermsEnum extends TermsEnum {
targetAutomata.clear();
targetAutomata.addAll(automata);
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(LevenshteinAutomataAttribute.class, "automata", automata);
}
}
}

View File

@ -18,6 +18,7 @@ package org.apache.lucene.search;
*/
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
import org.apache.lucene.util.BytesRef;
/** Implementation class for {@link MaxNonCompetitiveBoostAttribute}.
@ -59,4 +60,10 @@ public final class MaxNonCompetitiveBoostAttributeImpl extends AttributeImpl imp
t.setMaxNonCompetitiveBoost(maxNonCompetitiveBoost);
t.setCompetitiveTerm(competitiveTerm);
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(MaxNonCompetitiveBoostAttribute.class, "maxNonCompetitiveBoost", maxNonCompetitiveBoost);
reflector.reflect(MaxNonCompetitiveBoostAttribute.class, "competitiveTerm", competitiveTerm);
}
}

View File

@ -17,9 +17,6 @@ package org.apache.lucene.util;
* limitations under the License.
*/
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* Base class for Attributes that can be added to a
* {@link org.apache.lucene.util.AttributeSource}.
@ -48,17 +45,14 @@ public abstract class AttributeImpl implements Cloneable, Attribute {
*/
public final String reflectAsString(final boolean prependAttClass) {
final StringBuilder buffer = new StringBuilder();
reflectWith(new AttributeReflector() {
@Override
public void reflect(Class<? extends Attribute> attClass, String key, Object value) {
if (buffer.length() > 0) {
buffer.append(',');
}
if (prependAttClass) {
buffer.append(attClass.getName()).append('#');
}
buffer.append(key).append('=').append((value == null) ? "null" : value);
reflectWith((attClass, key, value) -> {
if (buffer.length() > 0) {
buffer.append(',');
}
if (prependAttClass) {
buffer.append(attClass.getName()).append('#');
}
buffer.append(key).append('=').append((value == null) ? "null" : value);
});
return buffer.toString();
}
@ -67,13 +61,7 @@ public abstract class AttributeImpl implements Cloneable, Attribute {
* This method is for introspection of attributes, it should simply
* add the key/values this attribute holds to the given {@link AttributeReflector}.
*
* <p>The default implementation calls {@link AttributeReflector#reflect} for all
* non-static fields from the implementing class, using the field name as key
* and the field value as value. The Attribute class is also determined by reflection.
* Please note that the default implementation can only handle single-Attribute
* implementations.
*
* <p>Custom implementations look like this (e.g. for a combined attribute implementation):
* <p>Implementations look like this (e.g. for a combined attribute implementation):
* <pre class="prettyprint">
* public void reflectWith(AttributeReflector reflector) {
* reflector.reflect(CharTermAttribute.class, "term", term());
@ -87,28 +75,7 @@ public abstract class AttributeImpl implements Cloneable, Attribute {
*
* @see #reflectAsString(boolean)
*/
public void reflectWith(AttributeReflector reflector) {
final Class<? extends AttributeImpl> clazz = this.getClass();
final Class<? extends Attribute>[] interfaces = AttributeSource.getAttributeInterfaces(clazz);
if (interfaces.length != 1) {
throw new UnsupportedOperationException(clazz.getName() +
" implements more than one Attribute interface, the default reflectWith() implementation cannot handle this.");
}
final Class<? extends Attribute> interf = interfaces[0];
final Field[] fields = clazz.getDeclaredFields();
try {
for (int i = 0; i < fields.length; i++) {
final Field f = fields[i];
if (Modifier.isStatic(f.getModifiers())) continue;
f.setAccessible(true);
reflector.reflect(interf, f.getName(), f.get(this));
}
} catch (IllegalAccessException e) {
// this should never happen, because we're just accessing fields
// from 'this'
throw new RuntimeException(e);
}
}
public abstract void reflectWith(AttributeReflector reflector);
/**
* Copies the values from this Attribute into the passed-in

View File

@ -20,6 +20,7 @@ package org.apache.lucene.util;
/**
* This interface is used to reflect contents of {@link AttributeSource} or {@link AttributeImpl}.
*/
@FunctionalInterface
public interface AttributeReflector {
/**

View File

@ -18,6 +18,7 @@ package org.apache.lucene.analysis;
*/
import org.apache.lucene.analysis.tokenattributes.*;
import org.apache.lucene.util.AttributeReflector;
import org.apache.lucene.util.LuceneTestCase;
import org.apache.lucene.util.Attribute;
import org.apache.lucene.util.AttributeImpl;
@ -94,6 +95,8 @@ public class TestToken extends LuceneTestCase {
public boolean equals(Object o) { return (o instanceof SenselessAttributeImpl); }
@Override
public int hashCode() { return 0; }
@Override
public void reflectWith(AttributeReflector reflector) {}
}
public void testTokenAttributeFactory() throws Exception {

View File

@ -38,6 +38,7 @@ import org.apache.lucene.store.MockDirectoryWrapper;
import org.apache.lucene.util.Attribute;
import org.apache.lucene.util.AttributeFactory;
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.LuceneTestCase.Monster;
import org.apache.lucene.util.LuceneTestCase.SuppressCodecs;
@ -45,6 +46,7 @@ import org.apache.lucene.util.LuceneTestCase.SuppressSysoutChecks;
import org.apache.lucene.util.LuceneTestCase;
import org.apache.lucene.util.TestUtil;
import org.apache.lucene.util.TimeUnits;
import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite;
// NOTE: SimpleText codec will consume very large amounts of
@ -126,6 +128,11 @@ public class Test2BTerms extends LuceneTestCase {
public MyTermAttributeImpl clone() {
throw new UnsupportedOperationException();
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(TermToBytesRefAttribute.class, "bytes", getBytesRef());
}
}
private static final class MyAttributeFactory extends AttributeFactory {

View File

@ -19,6 +19,7 @@ package org.apache.lucene.queryparser.flexible.spans;
import org.apache.lucene.queryparser.flexible.core.nodes.FieldableNode;
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
/**
* This attribute is used by the {@link UniqueFieldQueryNodeProcessor}
@ -85,8 +86,8 @@ public class UniqueFieldAttributeImpl extends AttributeImpl implements
}
@Override
public String toString() {
return "<uniqueField uniqueField='" + this.uniqueField + "'/>";
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(UniqueFieldAttribute.class, "uniqueField", uniqueField);
}
}

View File

@ -21,11 +21,13 @@ import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
import org.apache.lucene.document.GeoPointField;
import org.apache.lucene.index.FilteredTermsEnum;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.util.Attribute;
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
import org.apache.lucene.util.AttributeSource;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.BytesRefBuilder;
@ -226,6 +228,18 @@ class GeoPointTermsEnum extends FilteredTermsEnum {
targetRanges.clear();
targetRanges.addAll(rangeBounds);
}
@Override
public AttributeImpl clone() {
ComputedRangesAttributeImpl c = (ComputedRangesAttributeImpl) super.clone();;
copyTo(c);
return c;
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(ComputedRangesAttribute.class, "rangeBounds", rangeBounds);
}
}
/**

View File

@ -30,6 +30,7 @@ import org.apache.lucene.analysis.tokenattributes.PayloadAttribute;
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.BytesRefBuilder;
import org.apache.lucene.util.CharsRefBuilder;
@ -363,6 +364,11 @@ public final class CompletionTokenStream extends TokenStream {
return other;
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(TermToBytesRefAttribute.class, "bytes", getBytesRef());
}
@Override
public CharSequence toUTF16() {
if (charsRef == null) {

View File

@ -40,6 +40,7 @@ import org.apache.lucene.store.Directory;
import org.apache.lucene.util.Attribute;
import org.apache.lucene.util.AttributeFactory;
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
import org.apache.lucene.util.IOUtils;
import org.apache.lucene.util.LineFileDocs;
import org.apache.lucene.util.LuceneTestCase;
@ -106,6 +107,11 @@ public abstract class BaseTokenStreamTestCase extends LuceneTestCase {
public void copyTo(AttributeImpl target) {
((CheckClearAttributesAttributeImpl) target).clear();
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(CheckClearAttributesAttribute.class, "clearCalled", clearCalled);
}
}
// offsetsAreCorrect also validates:

View File

@ -60,6 +60,7 @@ import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.AttributeImpl;
import org.apache.lucene.util.AttributeReflector;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.FixedBitSet;
import org.apache.lucene.util.TestUtil;
@ -171,6 +172,12 @@ public abstract class BaseTermVectorsFormatTestCase extends BaseIndexFileFormatT
t.setOffset(start, end);
}
@Override
public void reflectWith(AttributeReflector reflector) {
reflector.reflect(OffsetAttribute.class, "startOffset", start);
reflector.reflect(OffsetAttribute.class, "endOffset", end);
}
}
// TODO: use CannedTokenStream?