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    
020    
021    /** 
022     * A name mapper which converts types to a hypenated String. So
023     * a bean type of FooBar will be converted to the element name "foo-bar".
024     * The name mapper can be configured to convert to upper case and to
025     * use a different separator via the <code>separator</code> and 
026     * <code>upperCase</code> properties, so that FooBar can be converted
027     * to FOO_BAR if needed, by calling the constructor
028     * <code>new HyphenatedNameMapper(true, "_")</code>.
029     * 
030     * @author <a href="mailto:jason@zenplex.com">Jason van Zyl</a>
031     * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
032     * @version $Revision: 471234 $
033     */
034    public class HyphenatedNameMapper implements NameMapper {
035    
036        /** the separator used to seperate words, which defaults to '-' */
037        private String separator = "-";
038    
039        /** whether upper or lower case conversions should be performed */
040        private boolean upperCase = false;
041        
042        /** 
043         * Construct a hyphenated name mapper that converts the name to lower case 
044         * and uses the default separator. 
045         */
046        public HyphenatedNameMapper() {
047        }
048        
049        /** 
050         * Construct a hyphenated name mapper with default separator.
051         *
052         * @param upperCase should the type name be converted (entirely) to upper case 
053         */
054        public HyphenatedNameMapper(boolean upperCase) {
055            this.upperCase = upperCase;
056        }
057        
058        /** 
059         * Construct a hyphenated name mapper.
060         *
061         * @param upperCase should the type name be converted (entirely) to upper case 
062         * @param separator use this string to separate the words in the name returned. 
063         * The words in the bean name are deduced by relying on the standard camel's hump
064         * property naming convention.
065         */
066        public HyphenatedNameMapper(boolean upperCase, String separator) {
067            this.upperCase = upperCase;
068            this.separator = separator;
069        }
070        
071        /**
072         * <p>The words within the bean name are deduced assuming the
073         * first-letter-capital (for example camel's hump) naming convention. For
074         * example, the words in <code>FooBar</code> are <code>foo</code>
075         * and <code>bar</code>.</p>
076         * 
077         * <p>Next convert all letter in the bean name to either upper case or lower case
078         * based on the {@link #isUpperCase} property value.</p>
079         *
080         * <p>Then the {@link #getSeparator} property value is inserted so that it separates
081         * each word.</p>
082         *
083         * @param typeName The name string to convert.  If a JavaBean
084         * class name, should included only the last part of the name
085         * rather than the fully qualified name (e.g. FooBar rather than
086         * org.example.FooBar).
087         * @return the bean name converted to either upper or lower case with words separated 
088         * by the separator.
089         */
090        public String mapTypeToElementName(String typeName) {
091            
092            int length = typeName.length();
093            if (length == 0) {
094                return "";
095            }
096            
097            StringBuffer sb = new StringBuffer();
098    
099            sb.append(convertChar(typeName.charAt(0)));        
100            
101            for (int i = 1; i < length; i++) {
102                if (Character.isUpperCase(typeName.charAt(i))) {
103                    sb.append(separator);
104                    sb.append(convertChar(typeName.charAt(i)));
105                } else {
106                    if ( upperCase ) {
107                        sb.append(convertChar(typeName.charAt(i)));
108                    } else {
109                        sb.append(typeName.charAt(i));
110                    }
111                }
112            } 
113            
114            return sb.toString();
115        }
116        
117        // Properties
118        //-------------------------------------------------------------------------        
119        /** 
120         * This separator will be inserted between the words in the bean name.
121         *
122         * @return the separator used to seperate words, which defaults to '-' 
123         */
124        public String getSeparator() {
125            return separator;
126        }
127        
128        /** 
129         * Sets the separator used to seperate words, which defaults to '-' 
130         *
131         * @param separator the string inserted to separate words
132         */
133        public void setSeparator(String separator) {
134            this.separator = separator;
135        }
136        
137        /** 
138         * <p>Should the bean name be converted to upper case?
139         * </p>
140         * <p>
141         * Otherwise, it will be converted to lower case.
142         * </p>
143         * @return whether upper or lower case conversions should be performed, 
144         * which defaults to false for lower case
145         */    
146        public boolean isUpperCase() {
147            return upperCase;
148        }
149        
150        /** 
151         * Sets whether upper or lower case conversions should be performed,
152         * which defaults to false for lower case.
153         *
154         * @param upperCase whether the name is to be converted to upper case
155         */    
156        public void setUpperCase(boolean upperCase) {
157            this.upperCase = upperCase;
158        }
159        
160        // Implementation methods
161        //-------------------------------------------------------------------------        
162        
163        /** 
164         * Performs type conversion on the given character based on whether
165         * upper or lower case conversions are being used
166         *
167         * @param ch the character to be converted
168         * @return converted to upper case if {@link #isUpperCase} otherwise to lower case 
169         */
170        protected char convertChar(char ch) {
171            if ( upperCase ) {
172                return Character.toUpperCase(ch);
173                
174            } else {
175                return Character.toLowerCase(ch);
176            }
177        }
178        
179        /**
180         * Outputs brief description.
181         * @since 0.8
182         */
183        public String toString() {
184            return "Hyphenated Name Mapper";
185        }
186    }