View Javadoc

1   /*
2    * Copyright 2001-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */ 
16  package org.apache.commons.betwixt.strategy;
17  
18  import java.util.Iterator;
19  import java.util.Map;
20  
21  import org.apache.commons.betwixt.ElementDescriptor;
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  
25  /*** 
26   * A default implementation of the plural name stemmer which
27   * tests for some common english plural/singular patterns and
28   * then uses a simple starts-with algorithm 
29   * 
30   * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
31   * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
32   * @version $Revision: 1.10 $
33   */
34  public class DefaultPluralStemmer implements PluralStemmer {
35  
36      /*** Log used for logging (Doh!) */
37      protected static Log log = LogFactory.getLog( DefaultPluralStemmer.class );
38  
39      /***
40       * <p>Algorithm supports common english plural patterns.</p>
41       *
42       * <p>First, common english plural constructions will be tried. 
43       * If the property doesn't end with <code>'y'</code> then this method will look for
44       * a property with which has <code>'es'</code> appended. 
45       * If the property ends with <code>'y'</code> then a property with the <code>'y'</code>
46       * replaced by <code>'ies'</code> will be searched for.</p>
47       *
48       * <p>If no matches are found then - if one exists - a property starting with the 
49       * singular name will be returned.</p>
50       * 
51       * @param propertyName the property name string to match
52       * @param map the <code>Map</code> containing the <code>ElementDescriptor</code>'s 
53       *        to be searched
54       * @return The plural descriptor for the given singular property name.
55       *         If more than one descriptor matches, then the best match is returned.
56       */
57      public ElementDescriptor findPluralDescriptor( String propertyName, Map map ) {
58          int foundKeyCount = 0;
59          String keyFound = null;
60          ElementDescriptor answer = (ElementDescriptor) map.get( propertyName + "s" );
61  
62          if ( answer == null && !propertyName.endsWith( "y" )) {
63              answer = (ElementDescriptor) map.get( propertyName + "es" );
64          }
65  
66          if ( answer == null ) {
67              int length = propertyName.length();
68              if ( propertyName.endsWith( "y" ) && length > 1 ) {
69                  String key = propertyName.substring(0, length - 1) + "ies";                
70                  answer = (ElementDescriptor) map.get( key );             
71              }
72              
73              if ( answer == null ) {
74                  // lets find the first one that starts with the propertyName
75                  for ( Iterator iter = map.keySet().iterator(); iter.hasNext(); ) {
76                      String key = (String) iter.next();
77                      if ( key.startsWith( propertyName ) ) {
78                          if (answer == null) {
79                              answer = (ElementDescriptor) map.get(key);
80                              if (key.equals(propertyName)) {
81                                  // we found the best match..
82                                  break;
83                              }
84                              foundKeyCount++;
85                              keyFound = key;
86                              
87                          } else {
88                              // check if we have a better match,,
89                              if (keyFound.length() > key.length()) {
90                                  answer = (ElementDescriptor) map.get(key);
91                                  keyFound = key;
92                              }
93                              foundKeyCount++;
94  
95                          }
96                      }
97                  }
98              }
99          }
100         if (foundKeyCount > 1) {
101             log.warn("More than one type matches, using closest match "+answer.getQualifiedName());
102         }
103         return answer;
104         
105     }
106 }