View Javadoc

1   /*
2    * Copyright (C) 2003-2004 Christian Siefkes <christian@siefkes.net>.
3    * Development of this software is supported by the German Research Society,
4    * Berlin-Brandenburg Graduate School in Distributed Information Systems
5    * (DFG grant no. GRK 316).
6    *
7    * This library is free software; you can redistribute it and/or
8    * modify it under the terms of the GNU Lesser General Public
9    * License as published by the Free Software Foundation; either
10   * version 2.1 of the License, or (at your option) any later version.
11   *
12   * This library is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this library; if not, visit
19   * http://www.gnu.org/licenses/lgpl.html or write to the Free Software
20   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21   */
22  package de.fu_berlin.ties.classify.feature;
23  
24  import org.apache.commons.lang.builder.ToStringBuilder;
25  
26  /***
27   * An abstract base class for immutable feature representation used for
28   * classification.
29   *
30   * @author Christian Siefkes
31   * @version $Revision: 1.2 $, $Date: 2004/05/31 19:13:49 $, $Author: siefkes $
32   */
33  public abstract class Feature {
34  
35      /***
36       * An optional comment on this feature, ignored for classification.
37       */
38      private final String comment;
39  
40      /***
41       * Creates a new instance, without storing a comment.
42       */
43      public Feature() {
44          this(null);
45      }
46  
47      /***
48       * Creates a new instance.
49       *
50       * @param myComment a comment on this feature, ignored for classification;
51       * might be <code>null</code>
52       */
53      public Feature(final String myComment) {
54          super();
55          comment = myComment;
56      }
57  
58      /***
59       * Indicates whether some other object is "equal to" this one, fulfulling
60       * the {@link Object#equals(java.lang.Object)} contract. To be considered
61       * equal, the object must be a {@link Feature}. If the
62       * {@linkplain #getRepresentation() representation} of this instance is not
63       * <code>null</code>, the representations of the two features are compared.
64       * Otherwise the {@linkplain #getFullRepresentation() full representations}
65       * are compared. Thus for normal features comments and other fields will
66       * be ignored. For comment-only features, comments will be considered,
67       * other fields will be ignored.
68       *
69       * @param obj the reference object with which to compare
70       * @return <code>true</code> iff the specified object is a
71       * {@link Feature} equal to this instance
72       */
73      public boolean equals(final Object obj) {
74          if (obj == this) {
75              return true;
76          } else if (obj instanceof Feature) {
77              final Feature other = (Feature) obj;
78              final String myRep = getRepresentation();
79              if (myRep != null) {
80                  // compare representations if present
81                  return myRep.equals(other.getRepresentation());
82              } else {
83                  // otherwise compare full representations (incl. comments)
84                  return getFullRepresentation().equals(
85                      other.getFullRepresentation());
86              }
87          } else {
88              return false;
89          }
90      }
91  
92      /***
93       * Returns the comment attached to this feature, if any.
94       *
95       * @return the comment, or <code>null</code> is no comment was stored
96       */
97      public String getComment() {
98          return comment;
99      }
100 
101     /***
102      * Prints a full representation of this feature that contains both
103      * representation (if any) and comment (if any). The comment is preceded
104      * by a "#" character.
105      *
106      * @return the full representation
107      */
108     public String getFullRepresentation() {
109         return getFullRepresentation("#");
110     }
111 
112     /***
113      * Prints a full representation of this feature that contains both
114      * representation (if any) and comment (if any). The comment is preceded by
115      * the specified <code>separator</code> (surrounded by spaces).
116      *
117      * @param separator used to introduce the comment
118      * @return the full representation
119      */
120     public String getFullRepresentation(final String separator) {
121         final StringBuffer result = new StringBuffer();
122         final String representation = getRepresentation();
123         if ((representation != null) && (representation.length() > 0)) {
124             result.append(representation);
125         }
126 
127         if ((comment != null) && (comment.length() > 0)) {
128             if (result.length() > 0) {
129                 result.append(' ');
130             }
131             result.append(separator).append(' ').append(comment);
132         }
133         return result.toString();
134     }
135 
136     /***
137      * Abstract method for returning the representation of this feature, to be
138      * used for classification.
139      *
140      * @return the feature representation, or <code>null</code> if this feature
141      * contains only a comment
142      */
143     public abstract String getRepresentation();
144 
145     /***
146      * Returns a strength value for this feature. This method can be
147      * overwritten to assign higher strenghts to more important or more frequent
148      * features. This implementation always returns 1.0.
149      *
150      * <p>Typically you should call {@link FeatureVector#strength(Feature)}
151      * instead of this method to allow feature vectors to modify the strenghts
152      * of the stored features.
153      *
154      * @return a strength value for this feature -- 1.0 in this implementation
155      */
156     public float getStrength() {
157         return 1.0f;
158     }
159 
160     /***
161      * Returns a hash code value for this object, fulfulling the
162      * {@link Object#hashCode()} contract.
163      * @return a hash code value for this object
164      */
165     public int hashCode() {
166         final String myRep = getRepresentation();
167         if (myRep != null) {
168             // hash representation if present
169             return myRep.hashCode();
170         } else {
171             // otherwise hash full representation (incl. comments)
172             return getFullRepresentation().hashCode();
173         }
174     }
175 
176     /***
177      * Returns a string representation of this object.
178      *
179      * @return a textual representation
180      */
181     public String toString() {
182         final ToStringBuilder builder = new ToStringBuilder(this);
183         if ((comment != null) && (comment.length() > 0)) {
184             builder.append("comment", comment);
185         }
186         return builder.toString();
187     }
188 
189 }