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.xbean.blueprint.generator;
018    
019    import java.io.File;
020    import java.io.FileWriter;
021    import java.io.IOException;
022    import java.io.PrintWriter;
023    import java.io.FileInputStream;
024    import java.io.InputStream;
025    import java.io.FileOutputStream;
026    import java.io.OutputStream;
027    import java.util.Iterator;
028    import java.util.List;
029    import java.util.Map;
030    import java.util.Set;
031    import java.util.Properties;
032    
033    import org.apache.xbean.blueprint.context.impl.NamespaceHelper;
034    
035    
036    /**
037     * @author Dain Sundstrom
038     * @version $Id$
039     * @since 1.0
040     */
041    public 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.blueprint.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    }