/*
 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.internal.xjc.model;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.namespace.QName;
import javax.xml.transform.Result;

import com.sun.codemodel.internal.JClass;
import com.sun.codemodel.internal.JCodeModel;
import com.sun.codemodel.internal.JPackage;
import com.sun.tools.internal.xjc.ErrorReceiver;
import com.sun.tools.internal.xjc.Options;
import com.sun.tools.internal.xjc.Plugin;
import com.sun.tools.internal.xjc.api.ClassNameAllocator;
import com.sun.tools.internal.xjc.generator.bean.BeanGenerator;
import com.sun.tools.internal.xjc.generator.bean.ImplStructureStrategy;
import com.sun.tools.internal.xjc.model.nav.NClass;
import com.sun.tools.internal.xjc.model.nav.NType;
import com.sun.tools.internal.xjc.model.nav.NavigatorImpl;
import com.sun.tools.internal.xjc.outline.Outline;
import com.sun.tools.internal.xjc.reader.xmlschema.Messages;
import com.sun.tools.internal.xjc.util.ErrorReceiverFilter;
import com.sun.xml.internal.bind.api.impl.NameConverter;
import com.sun.xml.internal.bind.v2.model.core.Ref;
import com.sun.xml.internal.bind.v2.model.core.TypeInfoSet;
import com.sun.xml.internal.bind.v2.model.nav.Navigator;
import com.sun.xml.internal.bind.v2.util.FlattenIterator;
import com.sun.xml.internal.xsom.XSComponent;
import com.sun.xml.internal.xsom.XSSchemaSet;

import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.LocatorImpl;

/**
 * Root of the object model that represents the code that needs to be generated.
 *
 * <p>
 * A {@link Model} is a schema language neutral representation of the
 * result of a schema parsing. The back-end then works against this model
 * to turn this into a series of Java source code.
 *
 * @author Kohsuke Kawaguchi
 */
public final class Model implements TypeInfoSet<NType,NClass,Void,Void>, CCustomizable {

    /**
     * Generated beans.
     */
    private final Map<NClass,CClassInfo> beans = new LinkedHashMap<NClass,CClassInfo>();

    /**
     * Generated enums.
     */
    private final Map<NClass,CEnumLeafInfo> enums = new LinkedHashMap<NClass,CEnumLeafInfo>();

    /**
     * The element mappings.
     */
    private final Map<NClass/*scope*/,Map<QName,CElementInfo>> elementMappings =
        new HashMap<NClass,Map<QName,CElementInfo>>();

    private final Iterable<? extends CElementInfo> allElements =
        new Iterable<CElementInfo>() {
            public Iterator<CElementInfo> iterator() {
                return new FlattenIterator<CElementInfo>(elementMappings.values());
            }
        };

    /**
     * {@link TypeUse}s for all named types.
     * <p>
     * I really don't want to promote the notion of a 'type' in any place except in the XML Schema code,
     * but this needs to be exposed for JAX-RPC. A reference to a named XML type will be converted into
     * a reference to a Java type with annotations.
     */
    private final Map<QName,TypeUse> typeUses = new LinkedHashMap<QName, TypeUse>();

    /**
     * {@link NameConverter} to be used.
     */
    private NameConverter nameConverter;

    /**
     * Single linked list that connects all {@link CCustomizations} that belong to this model.
     *
     * @see CCustomizations#next
     */
    /*package*/ CCustomizations customizations;

    /**
     * This field controls the generation of package level annotations for s2j
     */
    private boolean packageLevelAnnotations = true;

    /**
     * If this model was built from XML Schema, this field
     * stores the root object of the parse schema model.
     * Otherwise null.
     *
     * @sine 2.1.1
     */
    public final XSSchemaSet schemaComponent;

    private CCustomizations gloablCustomizations = new CCustomizations();

    /**
     * @param nc
     *      Usually this should be set in the constructor, but we do allow this parameter
     *      to be initially null, and then set later.
     * @param schemaComponent
     *      The source schema model, if this is built from XSD.
     */
    public Model( Options opts, JCodeModel cm, NameConverter nc, ClassNameAllocator allocator, XSSchemaSet schemaComponent ) {
        this.options = opts;
        this.codeModel = cm;
        this.nameConverter = nc;
        this.defaultSymbolSpace = new SymbolSpace(codeModel);
        defaultSymbolSpace.setType(codeModel.ref(Object.class));

        elementMappings.put(null,new HashMap<QName,CElementInfo>());

        if(opts.automaticNameConflictResolution)
            allocator = new AutoClassNameAllocator(allocator);
        this.allocator = new ClassNameAllocatorWrapper(allocator);
        this.schemaComponent = schemaComponent;
        this.gloablCustomizations.setParent(this,this);
    }

    public void setNameConverter(NameConverter nameConverter) {
        assert this.nameConverter==null;
        assert nameConverter!=null;
        this.nameConverter = nameConverter;
    }

    /**
     * Gets the name converter that shall be used to parse XML names into Java names.
     */
    public final NameConverter getNameConverter() {
        return nameConverter;
    }

    public boolean isPackageLevelAnnotations() {
        return packageLevelAnnotations;
    }

    public void setPackageLevelAnnotations(boolean packageLevelAnnotations) {
        this.packageLevelAnnotations = packageLevelAnnotations;
    }

    /**
     * This model uses this code model exclusively.
     */
    @XmlTransient
    public final JCodeModel codeModel;

    /**
     * Command-line options used for building this model.
     */
    public final Options options;

    /**
     * True to generate serializable classes.
     */
    @XmlAttribute
    public boolean serializable;

    /**
     * serial version UID to be generated.
     *
     * null if not to generate serialVersionUID field.
     */
    @XmlAttribute
    public Long serialVersionUID;

    /**
     * If non-null, all the generated classes should eventually derive from this class.
     */
    @XmlTransient
    public JClass rootClass;

    /**
     * If non-null, all the generated interfaces should eventually derive from this interface.
     */
    @XmlTransient
    public JClass rootInterface;

    /**
     * Specifies the code generation strategy.
     * Must not be null.
     */
    public ImplStructureStrategy strategy = ImplStructureStrategy.BEAN_ONLY;

    /**
     * This allocator has the final say on deciding the class name.
     * Must not be null.
     *
     * <p>
     * Model classes are responsible for using the allocator.
     * This allocator interaction should be transparent to the user/builder
     * of the model.
     */
    /*package*/ final ClassNameAllocatorWrapper allocator;

    /**
     * Default ID/IDREF symbol space. Any ID/IDREF without explicit
     * reference to a symbol space is assumed to use this default
     * symbol space.
     */
    @XmlTransient
    public final SymbolSpace defaultSymbolSpace;

    /** All the defined {@link SymbolSpace}s keyed by their name. */
    private final Map<String,SymbolSpace> symbolSpaces = new HashMap<String,SymbolSpace>();

    public SymbolSpace getSymbolSpace( String name ) {
        SymbolSpace ss = symbolSpaces.get(name);
        if(ss==null)
            symbolSpaces.put(name,ss=new SymbolSpace(codeModel));
        return ss;
    }

    /**
     * Fully-generate the source code into the given model.
     *
     * @return
     *      null if there was any errors. Otherwise it returns a valid
     *      {@link Outline} object, which captures how the model objects
     *      are mapped to the generated source code.
     *      <p>
     *      Add-ons can use those information to further augment the generated
     *      source code.
     */
    public Outline generateCode(Options opt,ErrorReceiver receiver) {
        ErrorReceiverFilter ehf = new ErrorReceiverFilter(receiver);

        // run extensions // moved to BGMBuilder._build() - issue with hyperjaxb3
//        for( Plugin ma : opt.activePlugins )
//            ma.postProcessModel(this,ehf);

        Outline o = BeanGenerator.generate(this, ehf);

        try {// run extensions
            for( Plugin ma : opt.activePlugins )
                ma.run(o,opt,ehf);
        } catch (SAXException e) {
            // fatal error. error should have been reported
            return null;
        }

        // check for unused plug-in customizations.
        // these can be only checked after the plug-ins run, so it's here.
        // the JAXB bindings are checked by XMLSchema's builder.
        Set<CCustomizations> check = new HashSet<CCustomizations>();
        for( CCustomizations c=customizations; c!=null; c=c.next ) {
            if(!check.add(c)) {
                throw new AssertionError(); // detect a loop
            }
            for (CPluginCustomization p : c) {
                if(!p.isAcknowledged()) {
                    ehf.error(
                        p.locator,
                        Messages.format(
                            Messages.ERR_UNACKNOWLEDGED_CUSTOMIZATION,
                            p.element.getNodeName()
                        ));
                    ehf.error(
                        c.getOwner().getLocator(),
                        Messages.format(
                            Messages.ERR_UNACKNOWLEDGED_CUSTOMIZATION_LOCATION));
                }
            }
        }

        if(ehf.hadError())
            o = null;
        return o;
    }

    /**
     * Represents the "top-level binding".
     *
     * <p>
     * This is used to support the use of a schema inside WSDL.
     * For XML Schema, the top-level binding is a map from
     * global element declarations to its representation class.
     *
     * <p>
     * For other schema languages, it should follow the appendicies in
     * WSDL (but in practice no one would use WSDL with a schema language
     * other than XML Schema, so it doesn't really matter.)
     *
     * <p>
     * This needs to be filled by the front-end.
     */
    public final Map<QName,CClassInfo> createTopLevelBindings() {
        Map<QName,CClassInfo> r = new HashMap<QName,CClassInfo>();
        for( CClassInfo b : beans().values() ) {
            if(b.isElement())
                r.put(b.getElementName(),b);
        }
        return r;
    }

    public Navigator<NType,NClass,Void,Void> getNavigator() {
        return NavigatorImpl.theInstance;
    }

    public CNonElement getTypeInfo(NType type) {
        CBuiltinLeafInfo leaf = CBuiltinLeafInfo.LEAVES.get(type);
        if(leaf!=null)      return leaf;

        return getClassInfo(getNavigator().asDecl(type));
    }

    public CBuiltinLeafInfo getAnyTypeInfo() {
        return CBuiltinLeafInfo.ANYTYPE;
    }

    public CNonElement getTypeInfo(Ref<NType,NClass> ref) {
        // TODO: handle XmlValueList
        assert !ref.valueList;
        return getTypeInfo(ref.type);
    }

    public Map<NClass,CClassInfo> beans() {
        return beans;
    }

    public Map<NClass,CEnumLeafInfo> enums() {
        return enums;
    }

    public Map<QName,TypeUse> typeUses() {
        return typeUses;
    }

    /**
     * No array mapping generation for XJC.
     */
    public Map<NType, ? extends CArrayInfo> arrays() {
        return Collections.emptyMap();
    }

    public Map<NType, ? extends CBuiltinLeafInfo> builtins() {
        return CBuiltinLeafInfo.LEAVES;
    }

    public CClassInfo getClassInfo(NClass t) {
        return beans.get(t);
    }

    public CElementInfo getElementInfo(NClass scope,QName name) {
        Map<QName,CElementInfo> m = elementMappings.get(scope);
        if(m!=null) {
            CElementInfo r = m.get(name);
            if(r!=null)     return r;
        }
        return elementMappings.get(null).get(name);
    }

    public Map<QName,CElementInfo> getElementMappings(NClass scope) {
        return elementMappings.get(scope);
    }

    public Iterable<? extends CElementInfo> getAllElements() {
        return allElements;
    }

    /**
     * @deprecated
     *      Always return null. Perhaps you are interested in {@link #schemaComponent}?
     */
    public XSComponent getSchemaComponent() {
        return null;
    }

    /**
     * @deprecated
     *      No line number available for the "root" component.
     */
    public Locator getLocator() {
        LocatorImpl r = new LocatorImpl();
        r.setLineNumber(-1);
        r.setColumnNumber(-1);
        return r;
    }

    /**
     * Gets the global customizations.
     */
    public CCustomizations getCustomizations() {
        return gloablCustomizations;
    }

    /**
     * Not implemented in the compile-time model.
     */
    public Map<String, String> getXmlNs(String namespaceUri) {
        return Collections.emptyMap();
    }

    public Map<String, String> getSchemaLocations() {
        return Collections.emptyMap();
    }

    public XmlNsForm getElementFormDefault(String nsUri) {
        throw new UnsupportedOperationException();
    }

    public XmlNsForm getAttributeFormDefault(String nsUri) {
        throw new UnsupportedOperationException();
    }

    public void dump(Result out) {
        // TODO
        throw new UnsupportedOperationException();
    }

    /*package*/ void add( CEnumLeafInfo e ) {
        enums.put( e.getClazz(), e );
    }

    /*package*/ void add( CClassInfo ci ) {
        beans.put( ci.getClazz(), ci );
    }

    /*package*/ void add( CElementInfo ei ) {
        NClass clazz = null;
        if(ei.getScope()!=null)
            clazz = ei.getScope().getClazz();

        Map<QName,CElementInfo> m = elementMappings.get(clazz);
        if(m==null)
            elementMappings.put(clazz,m=new HashMap<QName,CElementInfo>());
        m.put(ei.getElementName(),ei);
    }


    private final Map<JPackage,CClassInfoParent.Package> cache = new HashMap<JPackage,CClassInfoParent.Package>();

    public CClassInfoParent.Package getPackage(JPackage pkg) {
        CClassInfoParent.Package r = cache.get(pkg);
        if(r==null)
            cache.put(pkg,r=new CClassInfoParent.Package(pkg));
        return r;
    }

    /*package*/ static final Locator EMPTY_LOCATOR;

    static {
        LocatorImpl l = new LocatorImpl();
        l.setColumnNumber(-1);
        l.setLineNumber(-1);
        EMPTY_LOCATOR = l;
    }
}
