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