pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.4.0 / lucene / src / java / org / apache / lucene / util / AttributeSource.java
diff --git a/lucene-java-3.4.0/lucene/src/java/org/apache/lucene/util/AttributeSource.java b/lucene-java-3.4.0/lucene/src/java/org/apache/lucene/util/AttributeSource.java
deleted file mode 100644 (file)
index 6a14b90..0000000
+++ /dev/null
@@ -1,536 +0,0 @@
-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 java.lang.ref.WeakReference;
-import java.util.Collections;
-import java.util.NoSuchElementException;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.WeakHashMap;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.apache.lucene.analysis.TokenStream; // for javadocs
-import org.apache.lucene.analysis.tokenattributes.TermAttribute;
-import org.apache.lucene.analysis.tokenattributes.CharTermAttributeImpl;
-
-/**
- * An AttributeSource contains a list of different {@link AttributeImpl}s,
- * and methods to add and get them. There can only be a single instance
- * of an attribute in the same AttributeSource instance. This is ensured
- * by passing in the actual type of the Attribute (Class<Attribute>) to 
- * the {@link #addAttribute(Class)}, which then checks if an instance of
- * that type is already present. If yes, it returns the instance, otherwise
- * it creates a new instance and returns it.
- */
-public class AttributeSource {
-  /**
-   * An AttributeFactory creates instances of {@link AttributeImpl}s.
-   */
-  public static abstract class AttributeFactory {
-    /**
-     * returns an {@link AttributeImpl} for the supplied {@link Attribute} interface class.
-     */
-    public abstract AttributeImpl createAttributeInstance(Class<? extends Attribute> attClass);
-    
-    /**
-     * This is the default factory that creates {@link AttributeImpl}s using the
-     * class name of the supplied {@link Attribute} interface class by appending <code>Impl</code> to it.
-     */
-    public static final AttributeFactory DEFAULT_ATTRIBUTE_FACTORY = new DefaultAttributeFactory();
-    
-    private static final class DefaultAttributeFactory extends AttributeFactory {
-      private static final WeakHashMap<Class<? extends Attribute>, WeakReference<Class<? extends AttributeImpl>>> attClassImplMap =
-        new WeakHashMap<Class<? extends Attribute>, WeakReference<Class<? extends AttributeImpl>>>();
-      
-      private DefaultAttributeFactory() {}
-    
-      @Override
-      public AttributeImpl createAttributeInstance(Class<? extends Attribute> attClass) {
-        try {
-          return getClassForInterface(attClass).newInstance();
-        } catch (InstantiationException e) {
-          throw new IllegalArgumentException("Could not instantiate implementing class for " + attClass.getName());
-        } catch (IllegalAccessException e) {
-          throw new IllegalArgumentException("Could not instantiate implementing class for " + attClass.getName());
-        }
-      }
-      
-      private static Class<? extends AttributeImpl> getClassForInterface(Class<? extends Attribute> attClass) {
-        synchronized(attClassImplMap) {
-          final WeakReference<Class<? extends AttributeImpl>> ref = attClassImplMap.get(attClass);
-          Class<? extends AttributeImpl> clazz = (ref == null) ? null : ref.get();
-          if (clazz == null) {
-            try {
-              // TODO: Remove when TermAttribute is removed!
-              // This is a "sophisticated backwards compatibility hack"
-              // (enforce new impl for this deprecated att):
-              if (TermAttribute.class.equals(attClass)) {
-                clazz = CharTermAttributeImpl.class;
-              } else {
-                clazz = Class.forName(attClass.getName() + "Impl", true, attClass.getClassLoader())
-                  .asSubclass(AttributeImpl.class);
-              }
-              attClassImplMap.put(attClass,
-                new WeakReference<Class<? extends AttributeImpl>>(clazz)
-              );
-            } catch (ClassNotFoundException e) {
-              throw new IllegalArgumentException("Could not find implementing class for " + attClass.getName());
-            }
-          }
-          return clazz;
-        }
-      }
-    }
-  }
-      
-  /**
-   * This class holds the state of an AttributeSource.
-   * @see #captureState
-   * @see #restoreState
-   */
-  public static final class State implements Cloneable {
-    AttributeImpl attribute;
-    State next;
-    
-    @Override
-    public Object clone() {
-      State clone = new State();
-      clone.attribute = (AttributeImpl) attribute.clone();
-      
-      if (next != null) {
-        clone.next = (State) next.clone();
-      }
-      
-      return clone;
-    }
-  }
-    
-  // These two maps must always be in sync!!!
-  // So they are private, final and read-only from the outside (read-only iterators)
-  private final Map<Class<? extends Attribute>, AttributeImpl> attributes;
-  private final Map<Class<? extends AttributeImpl>, AttributeImpl> attributeImpls;
-  private final State[] currentState;
-
-  private AttributeFactory factory;
-  
-  /**
-   * An AttributeSource using the default attribute factory {@link AttributeSource.AttributeFactory#DEFAULT_ATTRIBUTE_FACTORY}.
-   */
-  public AttributeSource() {
-    this(AttributeFactory.DEFAULT_ATTRIBUTE_FACTORY);
-  }
-  
-  /**
-   * An AttributeSource that uses the same attributes as the supplied one.
-   */
-  public AttributeSource(AttributeSource input) {
-    if (input == null) {
-      throw new IllegalArgumentException("input AttributeSource must not be null");
-    }
-    this.attributes = input.attributes;
-    this.attributeImpls = input.attributeImpls;
-    this.currentState = input.currentState;
-    this.factory = input.factory;
-  }
-  
-  /**
-   * An AttributeSource using the supplied {@link AttributeFactory} for creating new {@link Attribute} instances.
-   */
-  public AttributeSource(AttributeFactory factory) {
-    this.attributes = new LinkedHashMap<Class<? extends Attribute>, AttributeImpl>();
-    this.attributeImpls = new LinkedHashMap<Class<? extends AttributeImpl>, AttributeImpl>();
-    this.currentState = new State[1];
-    this.factory = factory;
-  }
-  
-  /**
-   * returns the used AttributeFactory.
-   */
-  public AttributeFactory getAttributeFactory() {
-    return this.factory;
-  }
-  
-  /** Returns a new iterator that iterates the attribute classes
-   * in the same order they were added in.
-   */
-  public Iterator<Class<? extends Attribute>> getAttributeClassesIterator() {
-    return Collections.unmodifiableSet(attributes.keySet()).iterator();
-  }
-  
-  /** Returns a new iterator that iterates all unique Attribute implementations.
-   * This iterator may contain less entries that {@link #getAttributeClassesIterator},
-   * if one instance implements more than one Attribute interface.
-   */
-  public Iterator<AttributeImpl> getAttributeImplsIterator() {
-    final State initState = getCurrentState();
-    if (initState != null) {
-      return new Iterator<AttributeImpl>() {
-        private State state = initState;
-      
-        public void remove() {
-          throw new UnsupportedOperationException();
-        }
-        
-        public AttributeImpl next() {
-          if (state == null)
-            throw new NoSuchElementException();
-          final AttributeImpl att = state.attribute;
-          state = state.next;
-          return att;
-        }
-        
-        public boolean hasNext() {
-          return state != null;
-        }
-      };
-    } else {
-      return Collections.<AttributeImpl>emptySet().iterator();
-    }
-  }
-  
-  /** a cache that stores all interfaces for known implementation classes for performance (slow reflection) */
-  private static final WeakHashMap<Class<? extends AttributeImpl>,LinkedList<WeakReference<Class<? extends Attribute>>>> knownImplClasses =
-    new WeakHashMap<Class<? extends AttributeImpl>,LinkedList<WeakReference<Class<? extends Attribute>>>>();
-  
-  static LinkedList<WeakReference<Class<? extends Attribute>>> getAttributeInterfaces(final Class<? extends AttributeImpl> clazz) {
-    synchronized(knownImplClasses) {
-      LinkedList<WeakReference<Class<? extends Attribute>>> foundInterfaces = knownImplClasses.get(clazz);
-      if (foundInterfaces == null) {
-        // we have a strong reference to the class instance holding all interfaces in the list (parameter "att"),
-        // so all WeakReferences are never evicted by GC
-        knownImplClasses.put(clazz, foundInterfaces = new LinkedList<WeakReference<Class<? extends Attribute>>>());
-        // find all interfaces that this attribute instance implements
-        // and that extend the Attribute interface
-        Class<?> actClazz = clazz;
-        do {
-          for (Class<?> curInterface : actClazz.getInterfaces()) {
-            if (curInterface != Attribute.class && Attribute.class.isAssignableFrom(curInterface)) {
-              foundInterfaces.add(new WeakReference<Class<? extends Attribute>>(curInterface.asSubclass(Attribute.class)));
-            }
-          }
-          actClazz = actClazz.getSuperclass();
-        } while (actClazz != null);
-      }
-      return foundInterfaces;
-    }
-  }
-  
-  /** <b>Expert:</b> Adds a custom AttributeImpl instance with one or more Attribute interfaces.
-   * <p><font color="red"><b>Please note:</b> It is not guaranteed, that <code>att</code> is added to
-   * the <code>AttributeSource</code>, 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}.
-   * </font></p>
-   */
-  public void addAttributeImpl(final AttributeImpl att) {
-    final Class<? extends AttributeImpl> clazz = att.getClass();
-    if (attributeImpls.containsKey(clazz)) return;
-    final LinkedList<WeakReference<Class<? extends Attribute>>> foundInterfaces =
-      getAttributeInterfaces(clazz);
-    
-    // add all interfaces of this AttributeImpl to the maps
-    for (WeakReference<Class<? extends Attribute>> curInterfaceRef : foundInterfaces) {
-      final Class<? extends Attribute> curInterface = curInterfaceRef.get();
-      assert (curInterface != null) :
-        "We have a strong reference on the class holding the interfaces, so they should never get evicted";
-      // Attribute is a superclass of this interface
-      if (!attributes.containsKey(curInterface)) {
-        // invalidate state to force recomputation in captureState()
-        this.currentState[0] = null;
-        attributes.put(curInterface, att);
-        attributeImpls.put(clazz, att);
-      }
-    }
-  }
-  
-  /**
-   * The caller must pass in a Class&lt;? extends Attribute&gt; value.
-   * This method first checks if an instance of that class is 
-   * already in this AttributeSource and returns it. Otherwise a
-   * new instance is created, added to this AttributeSource and returned. 
-   */
-  public <A extends Attribute> A addAttribute(Class<A> attClass) {
-    AttributeImpl attImpl = attributes.get(attClass);
-    if (attImpl == null) {
-      if (!(attClass.isInterface() && Attribute.class.isAssignableFrom(attClass))) {
-        throw new IllegalArgumentException(
-          "addAttribute() only accepts an interface that extends Attribute, but " +
-          attClass.getName() + " does not fulfil this contract."
-        );
-      }
-      addAttributeImpl(attImpl = this.factory.createAttributeInstance(attClass));
-    }
-    return attClass.cast(attImpl);
-  }
-  
-  /** Returns true, iff this AttributeSource has any attributes */
-  public boolean hasAttributes() {
-    return !this.attributes.isEmpty();
-  }
-
-  /**
-   * The caller must pass in a Class&lt;? extends Attribute&gt; value. 
-   * Returns true, iff this AttributeSource contains the passed-in Attribute.
-   */
-  public boolean hasAttribute(Class<? extends Attribute> attClass) {
-    return this.attributes.containsKey(attClass);
-  }
-
-  /**
-   * The caller must pass in a Class&lt;? extends Attribute&gt; value. 
-   * Returns the instance of the passed in Attribute contained in this AttributeSource
-   * 
-   * @throws IllegalArgumentException if this AttributeSource does not contain the
-   *         Attribute. It is recommended to always use {@link #addAttribute} even in consumers
-   *         of TokenStreams, because you cannot know if a specific TokenStream really uses
-   *         a specific Attribute. {@link #addAttribute} will automatically make the attribute
-   *         available. If you want to only use the attribute, if it is available (to optimize
-   *         consuming), use {@link #hasAttribute}.
-   */
-  public <A extends Attribute> A getAttribute(Class<A> attClass) {
-    AttributeImpl attImpl = attributes.get(attClass);
-    if (attImpl == null) {
-      throw new IllegalArgumentException("This AttributeSource does not have the attribute '" + attClass.getName() + "'.");
-    }
-    return attClass.cast(attImpl);
-  }
-    
-  private State getCurrentState() {
-    State s  = currentState[0];
-    if (s != null || !hasAttributes()) {
-      return s;
-    }
-    State c = s = currentState[0] = new State();
-    final Iterator<AttributeImpl> it = attributeImpls.values().iterator();
-    c.attribute = it.next();
-    while (it.hasNext()) {
-      c.next = new State();
-      c = c.next;
-      c.attribute = it.next();
-    }
-    return s;
-  }
-  
-  /**
-   * Resets all Attributes in this AttributeSource by calling
-   * {@link AttributeImpl#clear()} on each Attribute implementation.
-   */
-  public void clearAttributes() {
-    for (State state = getCurrentState(); state != null; state = state.next) {
-      state.attribute.clear();
-    }
-  }
-  
-  /**
-   * Captures the state of all Attributes. The return value can be passed to
-   * {@link #restoreState} to restore the state of this or another AttributeSource.
-   */
-  public State captureState() {
-    final State state = this.getCurrentState();
-    return (state == null) ? null : (State) state.clone();
-  }
-  
-  /**
-   * Restores this state by copying the values of all attribute implementations
-   * that this state contains into the attributes implementations of the targetStream.
-   * The targetStream must contain a corresponding instance for each argument
-   * contained in this state (e.g. it is not possible to restore the state of
-   * an AttributeSource containing a TermAttribute into a AttributeSource using
-   * a Token instance as implementation).
-   * <p>
-   * 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 AttributeImpl of type " +
-          state.attribute.getClass().getName() + " that is not in in this AttributeSource");
-      }
-      state.attribute.copyTo(targetImpl);
-      state = state.next;
-    } while (state != null);
-  }
-
-  @Override
-  public int hashCode() {
-    int code = 0;
-    for (State state = getCurrentState(); 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
-        State thisState = this.getCurrentState();
-        State otherState = other.getCurrentState();
-        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;
-  }
-  
-  /**
-   * Returns a string representation of the object. In general, the {@code toString} method
-   * returns a string that &quot;textually represents&quot; this object.
-   *
-   * <p><b>WARNING:</b> For backwards compatibility this method is implemented as
-   * in Lucene 2.9/3.0. In Lucene 4.0 this default implementation
-   * will be removed.
-   *
-   * <p>It is recommeneded to use {@link #reflectAsString} or {@link #reflectWith}
-   * to get a well-defined output of AttributeSource's internals.
-   */
-  // TODO: @deprecated remove this method in 4.0
-  @Override
-  public String toString() {
-    final StringBuilder sb = new StringBuilder().append('(');
-    if (hasAttributes()) {
-      for (State state = getCurrentState(); state != null; state = state.next) {
-        if (sb.length() > 1) sb.append(',');
-        sb.append(state.attribute.toString());
-      }
-    }
-    return sb.append(')').toString();
-  }
-  
-  /**
-   * This method returns the current attribute values as a string in the following format
-   * by calling the {@link #reflectWith(AttributeReflector)} method:
-   * 
-   * <ul>
-   * <li><em>iff {@code prependAttClass=true}:</em> {@code "AttributeClass#key=value,AttributeClass#key=value"}
-   * <li><em>iff {@code prependAttClass=false}:</em> {@code "key=value,key=value"}
-   * </ul>
-   *
-   * @see #reflectWith(AttributeReflector)
-   */
-  public final String reflectAsString(final boolean prependAttClass) {
-    final StringBuilder buffer = new StringBuilder();
-    reflectWith(new AttributeReflector() {
-      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);
-      }
-    });
-    return buffer.toString();
-  }
-  
-  /**
-   * This method is for introspection of attributes, it should simply
-   * add the key/values this AttributeSource holds to the given {@link AttributeReflector}.
-   *
-   * <p>This method iterates over all Attribute implementations and calls the
-   * corresponding {@link AttributeImpl#reflectWith} method.</p>
-   *
-   * @see AttributeImpl#reflectWith
-   */
-  public final void reflectWith(AttributeReflector reflector) {
-    for (State state = getCurrentState(); state != null; state = state.next) {
-      state.attribute.reflectWith(reflector);
-    }
-  }
-
-  /**
-   * Performs a clone of all {@link AttributeImpl} instances returned in a new
-   * {@code AttributeSource} instance. This method can be used to e.g. create another TokenStream
-   * with exactly the same attributes (using {@link #AttributeSource(AttributeSource)}).
-   * You can also use it as a (non-performant) replacement for {@link #captureState}, if you need to look
-   * into / modify the captured state.
-   */
-  public AttributeSource cloneAttributes() {
-    final AttributeSource clone = new AttributeSource(this.factory);
-    
-    if (hasAttributes()) {
-      // first clone the impls
-      for (State state = getCurrentState(); state != null; state = state.next) {
-        clone.attributeImpls.put(state.attribute.getClass(), (AttributeImpl) state.attribute.clone());
-      }
-      
-      // now the interfaces
-      for (Entry<Class<? extends Attribute>, AttributeImpl> entry : this.attributes.entrySet()) {
-        clone.attributes.put(entry.getKey(), clone.attributeImpls.get(entry.getValue().getClass()));
-      }
-    }
-    
-    return clone;
-  }
-  
-  /**
-   * Copies the contents of this {@code AttributeSource} to the given target {@code AttributeSource}.
-   * The given instance has to provide all {@link Attribute}s this instance contains. 
-   * The actual attribute implementations must be identical in both {@code AttributeSource} instances;
-   * ideally both AttributeSource instances should use the same {@link AttributeFactory}.
-   * You can use this method as a replacement for {@link #restoreState}, if you use
-   * {@link #cloneAttributes} instead of {@link #captureState}.
-   */
-  public final void copyTo(AttributeSource target) {
-    for (State state = getCurrentState(); state != null; state = state.next) {
-      final AttributeImpl targetImpl = target.attributeImpls.get(state.attribute.getClass());
-      if (targetImpl == null) {
-        throw new IllegalArgumentException("This AttributeSource contains AttributeImpl of type " +
-          state.attribute.getClass().getName() + " that is not in the target");
-      }
-      state.attribute.copyTo(targetImpl);
-    }
-  }
-
-}