001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.betwixt.strategy; 018 019 import java.util.Iterator; 020 import java.util.Map; 021 022 import org.apache.commons.betwixt.ElementDescriptor; 023 import org.apache.commons.logging.Log; 024 import org.apache.commons.logging.LogFactory; 025 026 /** 027 * A default implementation of the plural name stemmer which 028 * tests for some common english plural/singular patterns and 029 * then uses a simple starts-with algorithm 030 * 031 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a> 032 * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a> 033 * @version $Revision: 438373 $ 034 */ 035 public class DefaultPluralStemmer implements PluralStemmer { 036 037 /** Log used for logging (Doh!) */ 038 protected static Log log = LogFactory.getLog( DefaultPluralStemmer.class ); 039 040 /** 041 * <p>Algorithm supports common english plural patterns.</p> 042 * 043 * <p>First, common english plural constructions will be tried. 044 * If the property doesn't end with <code>'y'</code> then this method will look for 045 * a property with which has <code>'es'</code> appended. 046 * If the property ends with <code>'y'</code> then a property with the <code>'y'</code> 047 * replaced by <code>'ies'</code> will be searched for.</p> 048 * 049 * <p>If no matches are found then - if one exists - a property starting with the 050 * singular name will be returned.</p> 051 * 052 * @param propertyName the property name string to match 053 * @param map the <code>Map</code> containing the <code>ElementDescriptor</code>'s 054 * to be searched 055 * @return The plural descriptor for the given singular property name. 056 * If more than one descriptor matches, then the best match is returned. 057 */ 058 public ElementDescriptor findPluralDescriptor( String propertyName, Map map ) { 059 int foundKeyCount = 0; 060 String keyFound = null; 061 ElementDescriptor answer = (ElementDescriptor) map.get( propertyName + "s" ); 062 063 if ( answer == null && !propertyName.endsWith( "y" )) { 064 answer = (ElementDescriptor) map.get( propertyName + "es" ); 065 } 066 067 if ( answer == null ) { 068 int length = propertyName.length(); 069 if ( propertyName.endsWith( "y" ) && length > 1 ) { 070 String key = propertyName.substring(0, length - 1) + "ies"; 071 answer = (ElementDescriptor) map.get( key ); 072 } 073 074 if ( answer == null ) { 075 // lets find the first one that starts with the propertyName 076 for ( Iterator iter = map.keySet().iterator(); iter.hasNext(); ) { 077 String key = (String) iter.next(); 078 if ( key.startsWith( propertyName ) ) { 079 if (answer == null) { 080 answer = (ElementDescriptor) map.get(key); 081 if (key.equals(propertyName)) { 082 // we found the best match.. 083 break; 084 } 085 foundKeyCount++; 086 keyFound = key; 087 088 } else { 089 // check if we have a better match,, 090 if (keyFound.length() > key.length()) { 091 answer = (ElementDescriptor) map.get(key); 092 keyFound = key; 093 } 094 foundKeyCount++; 095 096 } 097 } 098 } 099 } 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 }