/*
 * Copyright 2008 Filip Hianik
 *
 * 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.exolab.castor.builder.descriptors;

import org.exolab.castor.builder.BuilderConfiguration;
import org.exolab.javasource.JClass;
import org.exolab.javasource.JConstructor;
import org.exolab.javasource.JSourceCode;

/**
 * A class which defines the necessary methods for creating the JDO-specific
 * descriptor source files.
 * 
 * @see DescriptorJClass
 * @see DescriptorSourceFactory
 * 
 * @author Filip Hianik
 * @since 1.2.1
 * 
 */
public final class JDODescriptorJClass extends JClass {

    /** 
     * JDODescriptors extend this base class.
     */
    private static final String JDO_CLASS_DESCRIPTOR = 
        "org.exolab.castor.mapping.loader.ClassDescriptorImpl";

    /** 
     * The type being described by the Descriptor class we'll generate.
     */
    private final JClass _type;
    
    /** 
     * Source Builder configuration.
     */
    private final BuilderConfiguration _config;

    /**
     * Constructs a JDODescriptorJClass.
     * 
     * @param config
     *                Builder Configuration
     * @param className
     *                name of this descriptor class
     * @param type
     *                the type that is described by this descriptor
     */
    public JDODescriptorJClass(final BuilderConfiguration config,
            final String className, final JClass type) {
        super(className);
        this._config = config;
        this._type = type;
        init();
    }

    /**
     * Initializes this JDODescriptorJClass with the required methods.
     */
    private void init() {
        // Make sure that the Descriptor is extended JDOClassDescriptor even
        // when
        // the user has specified a super class for all the generated classes
        String superClass = null;
        if (_config != null) {
            superClass = _config.getProperty(
                    BuilderConfiguration.Property.SUPER_CLASS, null);
        }

        // boolean extended = false;

        if (_type.getSuperClassQualifiedName() == null
                || _type.getSuperClassQualifiedName().equals(superClass)) {
            setSuperClass(JDO_CLASS_DESCRIPTOR);
        } else {
            if (_type.getSuperClass() == null) {
                setSuperClass(null);
            } else {
                // extended = true;
                // setSuperClass(getSuperClassName());
            }
        }
        superClass = null;

        if (_type.getPackageName() != null
                && _type.getPackageName().length() > 0) {
            addImport(_type.getName());
        }

        // -- add default imports
        addImports();
        // -- add default contructor
        addDefaultConstructor();
    }

    /**
     * Adds our default imports.
     */
    private void addImports() {
        addImport("org.exolab.castor.jdo.engine.nature.ClassDescriptorJDONature");
        addImport("org.castor.jdo.engine.SQLTypeInfos");
//        addImport("org.exolab.castor.jdo.engine.JDOFieldDescriptor");
//        addImport("org.exolab.castor.jdo.engine.JDOFieldDescriptorImpl");
        addImport("org.exolab.castor.mapping.AccessMode");
        addImport("org.exolab.castor.mapping.FieldDescriptor");
        addImport("org.exolab.castor.mapping.FieldHandler");
        addImport("org.exolab.castor.mapping.MappingException");
        addImport("org.exolab.castor.mapping.loader.FieldHandlerImpl");
        addImport("org.exolab.castor.mapping.loader.TypeInfo");
        addImport("org.exolab.castor.mapping.xml.ClassChoice");
        addImport("org.exolab.castor.mapping.xml.ClassMapping");
        addImport("org.exolab.castor.mapping.xml.FieldMapping");
        addImport("org.exolab.castor.mapping.xml.MapTo");
        addImport("org.exolab.castor.mapping.xml.Sql");
        addImport("org.exolab.castor.mapping.xml.types.ClassMappingAccessType");
        addImport("org.castor.core.exception.IllegalClassDescriptorInitialization");
        addImport("org.exolab.castor.mapping.xml.types.FieldMappingCollectionType");
        addImport("org.exolab.castor.mapping.loader.FieldDescriptorImpl");
        addImport("org.exolab.castor.jdo.engine.nature.FieldDescriptorJDONature");
        addImport("java.lang.reflect.Method");
    }

    /**
     * Adds our default constructor.
     */
    private void addDefaultConstructor() {
        addConstructor(createConstructor());
        JConstructor cons = getConstructor(0);
        JSourceCode jsc = cons.getSourceCode();
        jsc.add("super();");
        jsc.add("ClassMapping mapping = new ClassMapping();");
        jsc.add("ClassChoice choice = new ClassChoice();");
        jsc.add("MapTo mapTo = new MapTo();");
    }
}