/**
 *
 * Copyright 2005 the original author or authors.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.xbean.spring.generator;

import org.xbean.spring.context.impl.NamespaceHelper;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * @author Dain Sundstrom
 * @version $Id$
 * @since 1.0
 */
public class XmlMetadataGenerator implements GeneratorPlugin {
    private final String metaInfDir;
    private final LogFacade log;

    public XmlMetadataGenerator(LogFacade log, String metaInfDir) {
        this.metaInfDir = metaInfDir;
        this.log = log;
    }

    public void generate(NamespaceMapping namespaceMapping) throws IOException {
        String namespace = namespaceMapping.getNamespace();
        if (namespace == null) {
            return;
        }

        File file = new File(metaInfDir + NamespaceHelper.createDiscoveryPathName(namespace));
        file.getParentFile().mkdirs();
        log.log("Generating META-INF properties file: " + file + " for namespace: " + namespace);
        PrintWriter out = new PrintWriter(new FileWriter(file));
        try {
            generatePropertiesFile(out, namespaceMapping.getElements());
        } finally {
            out.close();
        }
    }

    private void generatePropertiesFile(PrintWriter out, Set elements) {
        out.println("# NOTE: this file is autogenerated by XBeans");
        out.println();
        out.println("# beans");

        for (Iterator iter = elements.iterator(); iter.hasNext();) {
            ElementMapping element = (ElementMapping) iter.next();
            out.println(element.getElementName() + " = " + element.getClassName());

            generatePropertiesFileContent(out, element);
            generatePropertiesFilePropertyAliases(out, element);
            generatePropertiesFileConstructors(out, element);
            out.println();
        }
    }

    private void generatePropertiesFileContent(PrintWriter out, ElementMapping element) {
        String contentProperty = element.getContentProperty();
        if (contentProperty != null) {
            out.println(element.getElementName() + ".contentProperty = " + contentProperty);
        }
        String initMethod = element.getInitMethod();
        if (initMethod != null) {
            out.println(element.getElementName() + ".initMethod = " + initMethod);
        }

        String destroyMethod = element.getDestroyMethod();
        if (destroyMethod != null) {
            out.println(element.getElementName() + ".destroyMethod = " + destroyMethod);
        }

        String factoryMethod = element.getFactoryMethod();
        if (factoryMethod != null) {
            out.println(element.getElementName() + ".factoryMethod = " + factoryMethod);
        }
    }

    private void generatePropertiesFileConstructors(PrintWriter out, ElementMapping element) {
        List constructors = element.getConstructors();
        for (Iterator iterator = constructors.iterator(); iterator.hasNext();) {
            List args = (List) iterator.next();
            generatePropertiesFileConstructor(out, element, args);

        }
    }

    private void generatePropertiesFileConstructor(PrintWriter out, ElementMapping element, List args) {
        out.print(element.getClassName());
        if (element.getFactoryMethod() != null) {
            out.print("." + element.getFactoryMethod());
        }
        out.print("(");
        for (Iterator iterator = args.iterator(); iterator.hasNext();) {
            AttributeMapping attributeMapping = (AttributeMapping) iterator.next();
            out.print(attributeMapping.getType().getName());
            if (iterator.hasNext()) {
                out.print(",");
            }
        }
        out.print(").parameterNames =");
        for (Iterator iterator = args.iterator(); iterator.hasNext();) {
            AttributeMapping attributeMapping = (AttributeMapping) iterator.next();
            out.print(" ");
            out.print(attributeMapping.getPropertyName());
        }
        out.println();
    }

    private void generatePropertiesFilePropertyAliases(PrintWriter out, ElementMapping element) {
        for (Iterator iterator = element.getAttributes().iterator(); iterator.hasNext();) {
            AttributeMapping attributeMapping = (AttributeMapping) iterator.next();
            String propertyName = attributeMapping.getPropertyName();
            String attributeName = attributeMapping.getAttributeName();
            if (!propertyName.equals(attributeName)) {
                out.println(element.getElementName() + ".alias." + attributeName + " = " + propertyName);
            }
        }
    }
}

@@ -661,63 +661,8 @@
 r;%0A%0A
-import org.xbean.spring.context.impl.NamespaceHelper;%0A%0A
 impo
@@ -834,16 +834,72 @@
 l.Set;%0A%0A
+import org.xbean.spring.context.impl.NamespaceHelper;%0A%0A%0A
 /**%0A * @
@@ -5155,24 +5155,251 @@
 uteName)) %7B%0A
+                if (List.class.getName().equals(attributeMapping.getType().getName())) %7B%0A                    out.println(element.getElementName() + %22.list.%22 + attributeName + %22 = %22 + propertyName);%0A                %7D else %7B%0A    
             
@@ -5484,32 +5484,50 @@
  propertyName);%0A
+                %7D%0A
             %7D%0A  

Test to see if attribute is a list.