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 */
017package org.apache.xbean.spring.context.impl;
018
019import java.lang.reflect.Constructor;
020import java.lang.reflect.Method;
021import java.util.ArrayList;
022import java.util.Collections;
023import java.util.Properties;
024import java.util.StringTokenizer;
025
026/**
027 * A helper class which understands how to map an XML namespaced element to
028 * Spring bean configurations
029 *
030 * @author James Strachan
031 * @version $Id$
032 * @since 2.0
033 */
034public class MappingMetaData {
035    private Properties properties;
036    private String packageName;
037
038    /**
039     * Creates an empty MappingMetaData for the specified Java package.
040     * @param packageName the Java package to map
041     */
042    public MappingMetaData(String packageName) {
043        this.packageName = packageName;
044        this.properties = new Properties();
045    }
046
047    /**
048     * Creates MappingMetaData using the specified properties which contan the package name.
049     * @param properties
050     */
051    public MappingMetaData(Properties properties) {
052        this.properties = properties;
053    }
054
055    /**
056     * Returns the Java class name for the given XML element name
057     */
058    public String getClassName(String localName) {
059        String className = properties.getProperty(localName);
060        if (className == null && packageName != null) {
061            if (packageName.length() > 0) {
062                className = packageName + "." + localName;
063            }
064            else {
065                className = localName;
066            }
067        }
068        return className;
069    }
070
071    /**
072     * Returns the property name for the given element and attribute name
073     * 
074     * @param elementName the XML local name of the element
075     * @param attributeName the XML local name of the attribute
076     * @return the property name to use or null if the attribute is not a valid property
077     */
078    public String getPropertyName(String elementName, String attributeName) {
079        return properties.getProperty(elementName + ".alias." + attributeName, attributeName);
080    }
081
082    /**
083     * Returns a valid property name if the childElementName maps to a nested list property
084     * 
085     * @param elementName the owner element
086     * @param childElementName is the child element name which maps to the nested list property 
087     * @return the property name if available or null if it is not applicable
088     */
089    public String getNestedListProperty(String elementName, String childElementName) {
090        return properties.getProperty(elementName + ".list." + childElementName);
091    }
092    
093    /**
094     * Returns a valid property name if the childElementName maps to a nested bean property
095     * 
096     * @param elementName the owner element
097     * @param childElementName is the child element name which maps to the nested bean property 
098     * @return the property name if available or null if it is not applicable
099     */
100    public String getNestedProperty(String elementName, String childElementName) {
101        return properties.getProperty(elementName + ".alias." + childElementName);
102    }
103
104    public boolean isDefaultConstructor(Constructor constructor) {
105        String property = properties.getProperty(constructorToPropertyName(constructor) + ".default");
106        if (property != null) {
107            return Boolean.valueOf(property).booleanValue();
108        }
109        return false;
110    }
111
112    public boolean isDefaultFactoryMethod(Class beanClass, Method factoryMethod) {
113        String property = properties.getProperty(methodToPropertyName(beanClass, factoryMethod) + ".default");
114        if (property != null) {
115            return Boolean.valueOf(property).booleanValue();
116        }
117        return false;
118    }
119
120    public String[] getParameterNames(Constructor constructor) {
121        String property = properties.getProperty(constructorToPropertyName(constructor) + ".parameterNames");
122        if (property != null) {
123            ArrayList names = Collections.list(new StringTokenizer(property, ", "));
124            return (String[]) names.toArray(new String[0]);
125        }
126        return null;
127    }
128
129    public String[] getParameterNames(Class beanClass, Method factoryMethod) {
130        String property = properties.getProperty(methodToPropertyName(beanClass, factoryMethod) + ".parameterNames");
131        if (property != null) {
132            ArrayList names = Collections.list(new StringTokenizer(property, ", "));
133            return (String[]) names.toArray(new String[0]);
134        }
135        return null;
136    }
137
138    public static String constructorToPropertyName(Constructor constructor) {
139        StringBuffer buf = new StringBuffer();
140        buf.append(constructor.getName()).append("(");
141        Class[] parameterTypes = constructor.getParameterTypes();
142        for (int i = 0; i < parameterTypes.length; i++) {
143            Class parameterType = parameterTypes[i];
144            buf.append(parameterType.getName());
145            if (i < parameterTypes.length - 1) {
146                buf.append(",");
147            }
148        }
149        buf.append(")");
150        return buf.toString();
151    }
152
153    public static String methodToPropertyName(Class beanClass, Method method) {
154        StringBuffer buf = new StringBuffer();
155        buf.append(beanClass.getName()).append(".");
156        buf.append(method.getName()).append("(");
157        Class[] parameterTypes = method.getParameterTypes();
158        for (int i = 0; i < parameterTypes.length; i++) {
159            Class parameterType = parameterTypes[i];
160            buf.append(parameterType.getName());
161            if (i < parameterTypes.length - 1) {
162                buf.append(",");
163            }
164        }
165        buf.append(")");
166        return buf.toString();
167    }
168
169    public String getInitMethodName(String elementName) {
170        return properties.getProperty(elementName + ".initMethod");
171    }
172
173    public String getDestroyMethodName(String elementName) {
174        return properties.getProperty(elementName + ".destroyMethod");
175    }
176
177    public String getFactoryMethodName(String elementName) {
178        return properties.getProperty(elementName + ".factoryMethod");
179    }
180
181    public String getContentProperty(String elementName) {
182        return properties.getProperty(elementName + ".contentProperty");
183    }
184    
185    public String getMapEntryName(String elementName, String property) {
186        return properties.getProperty(elementName + "." + property + ".map.entryName");
187    }
188
189    public String getMapKeyName(String elementName, String property) {
190        return properties.getProperty(elementName + "." + property + ".map.keyName");
191    }
192
193    public boolean isFlatMap(String elementName, String property) {
194        return properties.getProperty(elementName + "." + property + ".map.flat") != null;
195    }
196    
197    public String getMapDupsMode(String elementName, String property) {
198        return properties.getProperty(elementName + "." + property + ".map.dups");
199    }
200    
201    public String getMapDefaultKey(String elementName, String property) {
202        return properties.getProperty(elementName + "." + property + ".map.defaultKey");
203    }
204    
205    public String getFlatCollectionProperty(String elementName, String property)
206    {
207        return properties.getProperty(elementName + "." + property + ".flatCollection");
208    }
209    
210    public boolean isFlatProperty(String elementName, String property)  {
211        return properties.getProperty(elementName + "." + property + ".flat") != null;
212    }
213    
214    public String getPropertyEditor(String elementName, String property)
215    {
216        return properties.getProperty(elementName + "." + property + ".propertyEditor");
217    }
218
219}