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.io.Serializable; 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}. * <p> * Attributes are used to add data in a dynamic, yet type-safe way to a source * of usually streamed objects, e. g. a {@link org.apache.lucene.analysis.TokenStream}. */ public abstract class AttributeImpl implements Cloneable, Serializable, Attribute { /** * Clears the values in this AttributeImpl and resets it to its * default value. If this implementation implements more than one Attribute interface * it clears all. */ public abstract void clear(); /** * The default implementation of this method accesses all declared * fields of this object and prints the values in the following syntax: * * <pre> * public String toString() { * return "start=" + startOffset + ",end=" + endOffset; * } * </pre> * * This method may be overridden by subclasses. */ @Override public String toString() { StringBuilder buffer = new StringBuilder(); Class<?> clazz = this.getClass(); Field[] fields = clazz.getDeclaredFields(); try { for (int i = 0; i < fields.length; i++) { Field f = fields[i]; if (Modifier.isStatic(f.getModifiers())) continue; f.setAccessible(true); Object value = f.get(this); if (buffer.length()>0) { buffer.append(','); } if (value == null) { buffer.append(f.getName() + "=null"); } else { buffer.append(f.getName() + "=" + value); } } } catch (IllegalAccessException e) { // this should never happen, because we're just accessing fields // from 'this' throw new RuntimeException(e); } return buffer.toString(); } /** * Subclasses must implement this method and should compute * a hashCode similar to this: * <pre> * public int hashCode() { * int code = startOffset; * code = code * 31 + endOffset; * return code; * } * </pre> * * see also {@link #equals(Object)} */ @Override public abstract int hashCode(); /** * All values used for computation of {@link #hashCode()} * should be checked here for equality. * * see also {@link Object#equals(Object)} */ @Override public abstract boolean equals(Object other); /** * Copies the values from this Attribute into the passed-in * target attribute. The target implementation must support all the * Attributes this implementation supports. */ public abstract void copyTo(AttributeImpl target); /** * Shallow clone. Subclasses must override this if they * need to clone any members deeply, */ @Override public Object clone() { Object clone = null; try { clone = super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException(e); // shouldn't happen } return clone; } }