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. import java.util.Iterator;
  18. import java.util.Map;
  19. import org.apache.commons.betwixt.ElementDescriptor;
  20. import org.apache.commons.logging.Log;
  21. import org.apache.commons.logging.LogFactory;
  22. /**
  23. * A default implementation of the plural name stemmer which
  24. * tests for some common english plural/singular patterns and
  25. * then uses a simple starts-with algorithm
  26. *
  27. * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  28. * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
  29. * @version $Revision: 1.10 $
  30. */
  31. public class DefaultPluralStemmer implements PluralStemmer {
  32. /** Log used for logging (Doh!) */
  33. protected static Log log = LogFactory.getLog( DefaultPluralStemmer.class );
  34. /**
  35. * <p>Algorithm supports common english plural patterns.</p>
  36. *
  37. * <p>First, common english plural constructions will be tried.
  38. * If the property doesn't end with <code>'y'</code> then this method will look for
  39. * a property with which has <code>'es'</code> appended.
  40. * If the property ends with <code>'y'</code> then a property with the <code>'y'</code>
  41. * replaced by <code>'ies'</code> will be searched for.</p>
  42. *
  43. * <p>If no matches are found then - if one exists - a property starting with the
  44. * singular name will be returned.</p>
  45. *
  46. * @param propertyName the property name string to match
  47. * @param map the <code>Map</code> containing the <code>ElementDescriptor</code>'s
  48. * to be searched
  49. * @return The plural descriptor for the given singular property name.
  50. * If more than one descriptor matches, then the best match is returned.
  51. */
  52. public ElementDescriptor findPluralDescriptor( String propertyName, Map map ) {
  53. int foundKeyCount = 0;
  54. String keyFound = null;
  55. ElementDescriptor answer = (ElementDescriptor) map.get( propertyName + "s" );
  56. if ( answer == null && !propertyName.endsWith( "y" )) {
  57. answer = (ElementDescriptor) map.get( propertyName + "es" );
  58. }
  59. if ( answer == null ) {
  60. int length = propertyName.length();
  61. if ( propertyName.endsWith( "y" ) && length > 1 ) {
  62. String key = propertyName.substring(0, length - 1) + "ies";
  63. answer = (ElementDescriptor) map.get( key );
  64. }
  65. if ( answer == null ) {
  66. // lets find the first one that starts with the propertyName
  67. for ( Iterator iter = map.keySet().iterator(); iter.hasNext(); ) {
  68. String key = (String) iter.next();
  69. if ( key.startsWith( propertyName ) ) {
  70. if (answer == null) {
  71. answer = (ElementDescriptor) map.get(key);
  72. if (key.equals(propertyName)) {
  73. // we found the best match..
  74. break;
  75. }
  76. foundKeyCount++;
  77. keyFound = key;
  78. } else {
  79. // check if we have a better match,,
  80. if (keyFound.length() > key.length()) {
  81. answer = (ElementDescriptor) map.get(key);
  82. keyFound = key;
  83. }
  84. foundKeyCount++;
  85. }
  86. }
  87. }
  88. }
  89. }
  90. if (foundKeyCount > 1) {
  91. log.warn("More than one type matches, using closest match "+answer.getQualifiedName());
  92. }
  93. return answer;
  94. }
  95. }