You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by us...@apache.org on 2015/07/02 18:18:52 UTC

svn commit: r1688855 - in /lucene/dev/trunk/lucene: ./ analysis/common/src/test/org/apache/lucene/analysis/compound/ analysis/morfologik/src/java/org/apache/lucene/analysis/morfologik/ core/src/java/org/apache/lucene/analysis/tokenattributes/ core/src/...

Author: uschindler
Date: Thu Jul  2 16:18:51 2015
New Revision: 1688855

URL: http://svn.apache.org/r1688855
Log:
LUCENE-6651: AttributeImpl#reflectWith(AttributeReflector) was made abstract and has no reflection-based default implementation anymore.

Modified:
    lucene/dev/trunk/lucene/CHANGES.txt
    lucene/dev/trunk/lucene/MIGRATE.txt
    lucene/dev/trunk/lucene/analysis/common/src/test/org/apache/lucene/analysis/compound/TestCompoundWordTokenFilter.java
    lucene/dev/trunk/lucene/analysis/morfologik/src/java/org/apache/lucene/analysis/morfologik/MorphosyntacticTagsAttributeImpl.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/FlagsAttributeImpl.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/KeywordAttributeImpl.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/OffsetAttributeImpl.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/PayloadAttributeImpl.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/PositionIncrementAttributeImpl.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/PositionLengthAttributeImpl.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/TypeAttributeImpl.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/BoostAttributeImpl.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/FuzzyTermsEnum.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/MaxNonCompetitiveBoostAttributeImpl.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/AttributeImpl.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/AttributeReflector.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/analysis/TestToken.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/Test2BTerms.java
    lucene/dev/trunk/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/spans/UniqueFieldAttributeImpl.java
    lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointTermsEnum.java
    lucene/dev/trunk/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/CompletionTokenStream.java
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/analysis/BaseTokenStreamTestCase.java
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/BaseTermVectorsFormatTestCase.java

Modified: lucene/dev/trunk/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/CHANGES.txt?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/CHANGES.txt (original)
+++ lucene/dev/trunk/lucene/CHANGES.txt Thu Jul  2 16:18:51 2015
@@ -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

Modified: lucene/dev/trunk/lucene/MIGRATE.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/MIGRATE.txt?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/MIGRATE.txt (original)
+++ lucene/dev/trunk/lucene/MIGRATE.txt Thu Jul  2 16:18:51 2015
@@ -40,3 +40,9 @@ can now be constructed this way using it
       .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.

Modified: lucene/dev/trunk/lucene/analysis/common/src/test/org/apache/lucene/analysis/compound/TestCompoundWordTokenFilter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/analysis/common/src/test/org/apache/lucene/analysis/compound/TestCompoundWordTokenFilter.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/analysis/common/src/test/org/apache/lucene/analysis/compound/TestCompoundWordTokenFilter.java (original)
+++ lucene/dev/trunk/lucene/analysis/common/src/test/org/apache/lucene/analysis/compound/TestCompoundWordTokenFilter.java Thu Jul  2 16:18:51 2015
@@ -36,6 +36,7 @@ import org.apache.lucene.analysis.util.C
 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
 
   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 {

Modified: lucene/dev/trunk/lucene/analysis/morfologik/src/java/org/apache/lucene/analysis/morfologik/MorphosyntacticTagsAttributeImpl.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/analysis/morfologik/src/java/org/apache/lucene/analysis/morfologik/MorphosyntacticTagsAttributeImpl.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/analysis/morfologik/src/java/org/apache/lucene/analysis/morfologik/MorphosyntacticTagsAttributeImpl.java (original)
+++ lucene/dev/trunk/lucene/analysis/morfologik/src/java/org/apache/lucene/analysis/morfologik/MorphosyntacticTagsAttributeImpl.java Thu Jul  2 16:18:51 2015
@@ -21,6 +21,7 @@ package org.apache.lucene.analysis.morfo
 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 MorphosyntacticTagsAttribut
     this.copyTo(cloned);
     return cloned;
   }
+
+  @Override
+  public void reflectWith(AttributeReflector reflector) {
+    reflector.reflect(MorphosyntacticTagsAttribute.class, "tags", tags);
+  }
 }

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/FlagsAttributeImpl.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/FlagsAttributeImpl.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/FlagsAttributeImpl.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/FlagsAttributeImpl.java Thu Jul  2 16:18:51 2015
@@ -18,6 +18,7 @@ package org.apache.lucene.analysis.token
  */
 
 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
     FlagsAttribute t = (FlagsAttribute) target;
     t.setFlags(flags);
   }
+
+  @Override
+  public void reflectWith(AttributeReflector reflector) {
+    reflector.reflect(FlagsAttribute.class, "flags", flags);
+  }
 }

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/KeywordAttributeImpl.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/KeywordAttributeImpl.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/KeywordAttributeImpl.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/KeywordAttributeImpl.java Thu Jul  2 16:18:51 2015
@@ -18,6 +18,7 @@ package org.apache.lucene.analysis.token
  */
 
 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
     keyword = isKeyword;
   }
 
+  @Override
+  public void reflectWith(AttributeReflector reflector) {
+    reflector.reflect(KeywordAttribute.class, "keyword", keyword);
+  }
 }

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/OffsetAttributeImpl.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/OffsetAttributeImpl.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/OffsetAttributeImpl.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/OffsetAttributeImpl.java Thu Jul  2 16:18:51 2015
@@ -18,6 +18,7 @@ package org.apache.lucene.analysis.token
  */
 
 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
     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);
+  }
 }

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/PayloadAttributeImpl.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/PayloadAttributeImpl.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/PayloadAttributeImpl.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/PayloadAttributeImpl.java Thu Jul  2 16:18:51 2015
@@ -18,6 +18,7 @@ package org.apache.lucene.analysis.token
  */
 
 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 extend
     t.setPayload((payload == null) ? null : BytesRef.deepCopyOf(payload));
   }  
 
-  
+  @Override
+  public void reflectWith(AttributeReflector reflector) {
+    reflector.reflect(PayloadAttribute.class, "payload", payload);
+  }
 }

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/PositionIncrementAttributeImpl.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/PositionIncrementAttributeImpl.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/PositionIncrementAttributeImpl.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/PositionIncrementAttributeImpl.java Thu Jul  2 16:18:51 2015
@@ -18,6 +18,7 @@ package org.apache.lucene.analysis.token
  */
 
 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 PositionIncrementAttributeI
     PositionIncrementAttribute t = (PositionIncrementAttribute) target;
     t.setPositionIncrement(positionIncrement);
   }  
+
+  @Override
+  public void reflectWith(AttributeReflector reflector) {
+    reflector.reflect(PositionIncrementAttribute.class, "positionIncrement", positionIncrement);
+  }
 }

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/PositionLengthAttributeImpl.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/PositionLengthAttributeImpl.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/PositionLengthAttributeImpl.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/PositionLengthAttributeImpl.java Thu Jul  2 16:18:51 2015
@@ -18,6 +18,7 @@ package org.apache.lucene.analysis.token
  */
 
 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
     PositionLengthAttribute t = (PositionLengthAttribute) target;
     t.setPositionLength(positionLength);
   }  
+
+  @Override
+  public void reflectWith(AttributeReflector reflector) {
+    reflector.reflect(PositionLengthAttribute.class, "positionLength", positionLength);
+  }
 }

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/TypeAttributeImpl.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/TypeAttributeImpl.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/TypeAttributeImpl.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/analysis/tokenattributes/TypeAttributeImpl.java Thu Jul  2 16:18:51 2015
@@ -18,6 +18,7 @@ package org.apache.lucene.analysis.token
  */
 
 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 A
     TypeAttribute t = (TypeAttribute) target;
     t.setType(type);
   }
+
+  @Override
+  public void reflectWith(AttributeReflector reflector) {
+    reflector.reflect(TypeAttribute.class, "type", type);
+  }
 }

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/BoostAttributeImpl.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/BoostAttributeImpl.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/BoostAttributeImpl.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/BoostAttributeImpl.java Thu Jul  2 16:18:51 2015
@@ -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 ex
   public void copyTo(AttributeImpl target) {
     ((BoostAttribute) target).setBoost(boost);
   }
+
+  @Override
+  public void reflectWith(AttributeReflector reflector) {
+    reflector.reflect(BoostAttribute.class, "boost", boost);
+  }
 }

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/FuzzyTermsEnum.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/FuzzyTermsEnum.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/FuzzyTermsEnum.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/FuzzyTermsEnum.java Thu Jul  2 16:18:51 2015
@@ -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 Term
       targetAutomata.clear();
       targetAutomata.addAll(automata);
     }
+
+    @Override
+    public void reflectWith(AttributeReflector reflector) {
+      reflector.reflect(LevenshteinAutomataAttribute.class, "automata", automata);
+    }
   }
 }

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/MaxNonCompetitiveBoostAttributeImpl.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/MaxNonCompetitiveBoostAttributeImpl.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/MaxNonCompetitiveBoostAttributeImpl.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/MaxNonCompetitiveBoostAttributeImpl.java Thu Jul  2 16:18:51 2015
@@ -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 MaxNonCompetitiveBoos
     t.setMaxNonCompetitiveBoost(maxNonCompetitiveBoost);
     t.setCompetitiveTerm(competitiveTerm);
   }
+
+  @Override
+  public void reflectWith(AttributeReflector reflector) {
+    reflector.reflect(MaxNonCompetitiveBoostAttribute.class, "maxNonCompetitiveBoost", maxNonCompetitiveBoost);
+    reflector.reflect(MaxNonCompetitiveBoostAttribute.class, "competitiveTerm", competitiveTerm);
+  }
 }

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/AttributeImpl.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/AttributeImpl.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/AttributeImpl.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/AttributeImpl.java Thu Jul  2 16:18:51 2015
@@ -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 impl
    */
   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 impl
    * 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 impl
    *
    * @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

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/AttributeReflector.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/AttributeReflector.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/AttributeReflector.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/AttributeReflector.java Thu Jul  2 16:18:51 2015
@@ -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 {
 
   /**

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/analysis/TestToken.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/analysis/TestToken.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/analysis/TestToken.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/analysis/TestToken.java Thu Jul  2 16:18:51 2015
@@ -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 LuceneTes
     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 {

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/Test2BTerms.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/Test2BTerms.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/Test2BTerms.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/Test2BTerms.java Thu Jul  2 16:18:51 2015
@@ -38,6 +38,7 @@ import org.apache.lucene.store.MockDirec
 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.LuceneTest
 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 LuceneT
       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 {

Modified: lucene/dev/trunk/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/spans/UniqueFieldAttributeImpl.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/spans/UniqueFieldAttributeImpl.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/spans/UniqueFieldAttributeImpl.java (original)
+++ lucene/dev/trunk/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/spans/UniqueFieldAttributeImpl.java Thu Jul  2 16:18:51 2015
@@ -19,6 +19,7 @@ package org.apache.lucene.queryparser.fl
 
 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 ex
   }
 
   @Override
-  public String toString() {
-    return "<uniqueField uniqueField='" + this.uniqueField + "'/>";
+  public void reflectWith(AttributeReflector reflector) {
+    reflector.reflect(UniqueFieldAttribute.class, "uniqueField", uniqueField);
   }
 
 }

Modified: lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointTermsEnum.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointTermsEnum.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointTermsEnum.java (original)
+++ lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointTermsEnum.java Thu Jul  2 16:18:51 2015
@@ -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 Filtered
       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);
+    }
   }
 
   /**

Modified: lucene/dev/trunk/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/CompletionTokenStream.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/CompletionTokenStream.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/CompletionTokenStream.java (original)
+++ lucene/dev/trunk/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/CompletionTokenStream.java Thu Jul  2 16:18:51 2015
@@ -30,6 +30,7 @@ import org.apache.lucene.analysis.tokena
 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;
@@ -364,6 +365,11 @@ public final class CompletionTokenStream
     }
 
     @Override
+    public void reflectWith(AttributeReflector reflector) {
+      reflector.reflect(TermToBytesRefAttribute.class, "bytes", getBytesRef());
+    }
+
+    @Override
     public CharSequence toUTF16() {
       if (charsRef == null) {
         charsRef = new CharsRefBuilder();

Modified: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/analysis/BaseTokenStreamTestCase.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/analysis/BaseTokenStreamTestCase.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/analysis/BaseTokenStreamTestCase.java (original)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/analysis/BaseTokenStreamTestCase.java Thu Jul  2 16:18:51 2015
@@ -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 BaseTokenStreamTes
     public void copyTo(AttributeImpl target) {
       ((CheckClearAttributesAttributeImpl) target).clear();
     }
+
+    @Override
+    public void reflectWith(AttributeReflector reflector) {
+      reflector.reflect(CheckClearAttributesAttribute.class, "clearCalled", clearCalled);
+    }
   }
 
   // offsetsAreCorrect also validates:

Modified: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/BaseTermVectorsFormatTestCase.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/BaseTermVectorsFormatTestCase.java?rev=1688855&r1=1688854&r2=1688855&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/BaseTermVectorsFormatTestCase.java (original)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/BaseTermVectorsFormatTestCase.java Thu Jul  2 16:18:51 2015
@@ -60,6 +60,7 @@ import org.apache.lucene.search.IndexSea
 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 BaseTermVectorsFor
       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?