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.generator;
018
019import java.io.File;
020import java.io.FileWriter;
021import java.io.IOException;
022import java.io.PrintWriter;
023import java.io.FileInputStream;
024import java.io.InputStream;
025import java.io.FileOutputStream;
026import java.io.OutputStream;
027import java.util.Iterator;
028import java.util.List;
029import java.util.Map;
030import java.util.Set;
031import java.util.Properties;
032
033import org.apache.xbean.spring.context.impl.NamespaceHelper;
034
035
036/**
037 * @author Dain Sundstrom
038 * @version $Id$
039 * @since 1.0
040 */
041public class XmlMetadataGenerator implements GeneratorPlugin {
042    private final String metaInfDir;
043    private LogFacade log;
044    private final File schema;
045
046    public static final String NAMESPACE_HANDLER = "org.apache.xbean.spring.context.v2.XBeanNamespaceHandler";
047        private final boolean generateSpringSchemasFile;
048        private final boolean generateSpringHandlersFile;
049
050    public XmlMetadataGenerator(String metaInfDir, File schema) {
051        this(metaInfDir, schema, true, true);
052    }
053    
054    public XmlMetadataGenerator(String metaInfDir, File schema, boolean generateSpringSchemasFile, boolean generateSpringHandlersFile) {
055        this.metaInfDir = metaInfDir;
056        this.schema = schema;
057                this.generateSpringSchemasFile = generateSpringSchemasFile;
058                this.generateSpringHandlersFile = generateSpringHandlersFile;
059    }
060
061    public void generate(NamespaceMapping namespaceMapping) throws IOException {
062        String namespace = namespaceMapping.getNamespace();
063        if (namespace == null) {
064            return;
065        }
066
067        File file = new File(metaInfDir, NamespaceHelper.createDiscoveryPathName(namespace));
068        file.getParentFile().mkdirs();
069        log.log("Generating META-INF properties file: " + file + " for namespace: " + namespace);
070        PrintWriter out = new PrintWriter(new FileWriter(file));
071        try {
072            generatePropertiesFile(out, namespaceMapping.getElements());
073        } finally {
074            out.close();
075        }
076        
077        if( generateSpringHandlersFile ) {
078                
079            // Generate spring 2.0 mapping
080                file = new File(metaInfDir, "META-INF/spring.handlers");
081
082            Properties properties = new Properties();
083            if (!file.exists()) {
084                log.log("Generating Spring 2.0 handler mapping: " + file + " for namespace: " + namespace);
085            } else {
086                log.log("Updating Spring 2.0 handler mapping: " + file + " for namespace: " + namespace);
087
088                // read in current file
089                InputStream in = new FileInputStream(file);
090                try {
091                    properties.load(in);
092                } catch (IOException e) {
093                    in.close();
094                }
095            }
096
097            // add property
098            properties.put(namespace,  NAMESPACE_HANDLER);
099
100            // write properties
101            OutputStream fout = new FileOutputStream(file);
102            try {
103                properties.store(fout, "Generated by xbean-spring");
104            } finally {
105                fout.close();
106            }
107        }
108
109        if (schema != null && generateSpringSchemasFile ) {
110            String cp = new File(metaInfDir).toURI().relativize(schema.toURI()).toString();
111            file = new File(metaInfDir, "META-INF/spring.schemas");
112
113            Properties properties = new Properties();
114            if (!file.exists()) {
115                log.log("Generating Spring 2.0 schema mapping: " + file + " for namespace: " + namespace);
116            } else {
117                log.log("Updating Spring 2.0 schema mapping: " + file + " for namespace: " + namespace);
118
119                // read in current file
120                InputStream in = new FileInputStream(file);
121                try {
122                    properties.load(in);
123                } catch (IOException e) {
124                    in.close();
125                }
126            }
127
128            // add property
129            String uri = namespace;
130            if (!uri.endsWith("/")) {
131                uri += "/";
132            }
133            properties.put(uri + cp,  cp);
134
135            // write properties
136            OutputStream fout = new FileOutputStream(file);
137            try {
138                properties.store(fout, "Generated by xbean-spring");
139            } finally {
140                fout.close();
141            }
142        }
143    }
144
145    private void generatePropertiesFile(PrintWriter out, Set elements) {
146        out.println("# NOTE: this file is autogenerated by Apache XBean");
147        out.println();
148        out.println("# beans");
149
150        for (Iterator iter = elements.iterator(); iter.hasNext();) {
151            ElementMapping element = (ElementMapping) iter.next();
152            out.println(element.getElementName() + " = " + element.getClassName());
153
154            generatePropertiesFileContent(out, element);
155            generatePropertiesFilePropertyAliases(out, element);
156            generatePropertiesFileConstructors(out, element);
157            out.println();
158        }
159    }
160
161    private void generatePropertiesFileContent(PrintWriter out, ElementMapping element) {
162        String contentProperty = element.getContentProperty();
163        if (contentProperty != null) {
164            out.println(element.getElementName() + ".contentProperty = " + contentProperty);
165        }
166        String initMethod = element.getInitMethod();
167        if (initMethod != null) {
168            out.println(element.getElementName() + ".initMethod = " + initMethod);
169        }
170
171        String destroyMethod = element.getDestroyMethod();
172        if (destroyMethod != null) {
173            out.println(element.getElementName() + ".destroyMethod = " + destroyMethod);
174        }
175
176        String factoryMethod = element.getFactoryMethod();
177        if (factoryMethod != null) {
178            out.println(element.getElementName() + ".factoryMethod = " + factoryMethod);
179        }
180
181        for (Iterator iter = element.getAttributes().iterator(); iter.hasNext();) {
182            AttributeMapping attribute = (AttributeMapping) iter.next();
183            if( attribute.getPropertyEditor() !=null ) {
184                out.println(element.getElementName() + "."+attribute.getPropertyName()+ ".propertyEditor = " + attribute.getPropertyEditor());
185            }
186        }
187
188        List flatProperties = element.getFlatProperties();
189        for (Iterator itr = flatProperties.iterator(); itr.hasNext();) {
190            out.println(element.getElementName() + "." + itr.next() + ".flat");
191        }
192
193        Map maps = element.getMapMappings();
194        for (Iterator itr = maps.entrySet().iterator(); itr.hasNext();) {
195            Map.Entry entry = (Map.Entry) itr.next();
196            MapMapping mm = (MapMapping) entry.getValue();
197            if (mm.getEntryName() != null) {
198                out.println(element.getElementName() + "." + entry.getKey() + ".map.entryName = " + mm.getEntryName());
199            }
200            if (mm.getKeyName() != null) {
201                out.println(element.getElementName() + "." + entry.getKey() + ".map.keyName = " + mm.getKeyName());
202            }
203            if (mm.isFlat()) {
204                out.println(element.getElementName() + "." + entry.getKey() + ".map.flat = " + Boolean.toString(mm.isFlat()));
205            }
206            if (mm.getDupsMode() != null) {
207                out.println(element.getElementName() + "." + entry.getKey() + ".map.dups = " + mm.getDupsMode());
208            }
209            if (mm.getDefaultKey() != null) {
210                out.println(element.getElementName() + "." + entry.getKey() + ".map.defaultKey = " + mm.getDefaultKey());
211            }
212        }
213
214        Map flatCollections = element.getFlatCollections();
215        for (Iterator itr = flatCollections.entrySet().iterator(); itr.hasNext();) {
216            Map.Entry entry = (Map.Entry) itr.next();
217            String child = (String) entry.getValue();
218            out.println(element.getElementName() + "." + child + ".flatCollection = " + entry.getKey());
219        }
220    }
221
222    private void generatePropertiesFileConstructors(PrintWriter out, ElementMapping element) {
223        List constructors = element.getConstructors();
224        for (Iterator iterator = constructors.iterator(); iterator.hasNext();) {
225            List args = (List) iterator.next();
226            generatePropertiesFileConstructor(out, element, args);
227        }
228    }
229
230    private void generatePropertiesFileConstructor(PrintWriter out, ElementMapping element, List args) {
231        out.print(element.getClassName());
232        if (element.getFactoryMethod() != null) {
233            out.print("." + element.getFactoryMethod());
234        }
235        out.print("(");
236        for (Iterator iterator = args.iterator(); iterator.hasNext();) {
237            ParameterMapping parameterMapping = (ParameterMapping) iterator.next();
238            out.print(parameterMapping.getType().getName());
239            if (iterator.hasNext()) {
240                out.print(",");
241            }
242        }
243        out.print(").parameterNames =");
244        for (Iterator iterator = args.iterator(); iterator.hasNext();) {
245            ParameterMapping parameterMapping = (ParameterMapping) iterator.next();
246            out.print(" ");
247            out.print(parameterMapping.getName());
248        }
249        out.println();
250    }
251
252    private void generatePropertiesFilePropertyAliases(PrintWriter out, ElementMapping element) {
253        for (Iterator iterator = element.getAttributes().iterator(); iterator.hasNext();) {
254            AttributeMapping attributeMapping = (AttributeMapping) iterator.next();
255            String propertyName = attributeMapping.getPropertyName();
256            String attributeName = attributeMapping.getAttributeName();
257            if (!propertyName.equals(attributeName)) {
258                if (List.class.getName().equals(attributeMapping.getType().getName())) {
259                    out.println(element.getElementName() + ".list." + attributeName + " = " + propertyName);
260                } else {
261                    out.println(element.getElementName() + ".alias." + attributeName + " = " + propertyName);
262                }
263            }
264        }
265    }
266
267    public LogFacade getLog() {
268        return log;
269    }
270
271    public void setLog(LogFacade log) {
272        this.log = log;
273    }
274}