View Javadoc

1   /*
2    * Copyright (C) 2004-2006 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 program is free software; you can redistribute it and/or modify
8    * it under the terms of the GNU General Public License as published by
9    * the Free Software Foundation; either version 2 of the License, or
10   * (at your option) any later version.
11   *
12   * This program 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
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with this program; if not, visit
19   * http://www.gnu.org/licenses/gpl.html or write to the Free Software
20   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21   */
22  package de.fu_berlin.ties.extract;
23  
24  import java.util.Collection;
25  import java.util.Collections;
26  import java.util.LinkedHashMap;
27  import java.util.Map;
28  import java.util.Set;
29  
30  import org.apache.commons.configuration.Configuration;
31  import org.apache.commons.lang.builder.EqualsBuilder;
32  import org.apache.commons.lang.builder.HashCodeBuilder;
33  import org.apache.commons.lang.builder.ToStringBuilder;
34  
35  import de.fu_berlin.ties.TiesConfiguration;
36  import de.fu_berlin.ties.util.Util;
37  
38  /***
39   * A target structure manages the classes of entities to recognize.
40   * Instances of this class are immutable and thus thread-safe.
41   *
42   * @author Christian Siefkes
43   * @version $Revision: 1.9 $, $Date: 2006/10/21 16:04:14 $, $Author: siefkes $
44   */
45  public class TargetStructure {
46  
47      /***
48       * Configuration key: names of the classes to recognize.
49       */
50      protected static final String CONFIG_TARGET_CLASSES = "classes";
51  
52      /***
53       * Maps from class names (String) to {@linkplain TargetClass}es.
54       * This map is immutable and cannot modified.
55       */
56      private final Map<String, TargetClass> classes;
57  
58      /***
59       * Creates a new instance using the
60       * {@linkplain TiesConfiguration#CONF standard configuration}.
61       */
62      public TargetStructure() {
63          this(TiesConfiguration.CONF);
64      }
65  
66      /***
67       * Creates a new instance using the provided configuration. Currently,
68       * the names of target classes are read from the
69       * {@link #CONFIG_TARGET_CLASSES} parameter.
70       *
71       * @param config used to configure this instance
72       */
73      public TargetStructure(final Configuration config) {
74          this(config.getStringArray(CONFIG_TARGET_CLASSES));
75  
76          if (getClassNames().isEmpty()) {
77              Util.LOG.warn("No target classes defined ("
78                  + CONFIG_TARGET_CLASSES + " parameter)");
79          }
80      }
81  
82      /***
83       * Creates a new instance using the provided class names.
84       *
85       * @param classNames the array of target classes
86       */
87      public TargetStructure(final String[] classNames) {
88          super();
89  
90          // using a linked hash set to preserve the order of definition
91          final LinkedHashMap<String, TargetClass> classMap =
92              new LinkedHashMap<String, TargetClass>();
93  
94          // create classes from specified names
95          for (int i = 0; i < classNames.length; i++) {
96              classMap.put(classNames[i], new TargetClass(classNames[i]));
97          }
98  
99          // store an immutable view on the map
100         classes = Collections.unmodifiableMap(classMap);
101     }
102 
103 
104     /***
105      * Returns the {@link TargetClass} object for a given class name, if
106      * defined in this target structure.
107      *
108      * @param name the name of the class to look up
109      * @return the {@link TargetClass} for the given name; or <code>null</code>
110      * if the class is not defined in this target structure
111      */
112     public TargetClass classForName(final String name) {
113         return classes.get(name);
114     }
115 
116     /***
117      * Returns the set of names of the target classes at the top of the
118      * inheritance hierarchy. This set is immutable and cannot modified.
119      *
120      * @return the set of class names
121      */
122     public Set getBaseClassNames() {
123         // currently, all class names are returned
124         return classes.keySet();
125     }
126 
127     /***
128      * Returns the {@link TargetClass}es at the top of the inheritance
129      * hierarchy. This collection is immutable and cannot modified.
130      *
131      * @return the defined target classes
132      */
133     public Collection getBaseTargetClasses() {
134         // currently, all classes are returned
135         return classes.values();
136     }
137 
138     /***
139      * Indicates whether some other object is "equal to" this one, fulfulling
140      * the {@link Object#equals(java.lang.Object)} contract.
141      *
142      * @param obj the reference object with which to compare
143      * @return <code>true</code> iff the specified object is a
144      * {@link TargetStructure} equal to this instance
145      */
146     public boolean equals(final Object obj) {
147         if (obj == this) {
148             return true;
149         } else if ((obj != null) && (getClass().equals(obj.getClass()))) {
150             // used getClass instead of instanceof because otherwise subclasses
151             // with additional fields would break the contract
152             final TargetStructure other = (TargetStructure) obj;
153             return new EqualsBuilder()
154                 .append(classes, other.classes)
155                 .isEquals();
156         } else {
157             return false;
158         }
159     }
160 
161     /***
162      * Returns the set of names of the defined target classes.
163      * This set is immutable and cannot modified.
164      *
165      * @return the set of class names
166      */
167     public Set<String> getClassNames() {
168         return classes.keySet();
169     }
170 
171     /***
172      * Returns the defined {@link TargetClass}es.
173      * This collection is immutable and cannot modified.
174      *
175      * @return the defined target classes
176      */
177     public Collection<TargetClass> getTargetClasses() {
178         return classes.values();
179     }
180 
181     /***
182      * Returns a hash code value for this object, fulfulling the
183      * {@link Object#hashCode()} contract.
184      *
185      * @return a hash code value for this object
186      */
187     public int hashCode() {
188         // you pick two hard-coded, randomly chosen, non-zero, odd numbers
189         // (preferably primes); ideally different for each class
190         return new HashCodeBuilder(19, 23)
191             .append(classes)
192             .toHashCode();
193     }
194 
195     /***
196      * Returns a string representation of this object.
197      * @return a textual representation
198      */
199     public String toString() {
200         return new ToStringBuilder(this)
201             // no need to duplicate the class names
202             .append("target classes", getTargetClasses())
203             .toString();
204     }
205 
206     /***
207      * Checks if a class name is valid. Dummy target structures (no class names
208      * defined) accept any class names as valid.
209      *
210      * @param className the name of the class to check
211      * @return <code>true</code> iff {@link #getClassNames()} contains
212      * <code>className</code> or {@link #getClassNames()} is empty
213      */
214     public boolean validClassName(final String className) {
215         return getClassNames().contains(className) || getClassNames().isEmpty();
216     }
217 
218 }