/*   Copyright 2004 The Apache Software Foundation
 *
 *   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.apache.xmlbeans.impl.inst2xsd;

import org.apache.xmlbeans.*;
import org.apache.xmlbeans.impl.common.PrefixResolver;
import org.apache.xmlbeans.impl.common.ValidationContext;
import org.apache.xmlbeans.impl.common.XmlWhitespace;
import org.apache.xmlbeans.impl.inst2xsd.util.Attribute;
import org.apache.xmlbeans.impl.inst2xsd.util.Element;
import org.apache.xmlbeans.impl.inst2xsd.util.TypeSystemHolder;
import org.apache.xmlbeans.impl.inst2xsd.util.Type;
import org.apache.xmlbeans.impl.util.XsTypeConverter;
import org.apache.xmlbeans.impl.values.*;

import javax.xml.namespace.QName;
import java.util.*;

/**
 * @author Cezar Andrei ( cezar.andrei at bea.com )
 * Date: Jul 26, 2004
 */
public class RussianDollStrategy
    implements XsdGenStrategy
{
    static final String _xsi         = "http://www.w3.org/2001/XMLSchema-instance";

    static final QName _xsiNil          = new QName( _xsi, "nil", "xsi" );
    static final QName _xsiType         = new QName( _xsi, "type", "xsi" );

    public void processDoc(XmlObject[] instances, Inst2XsdOptions options, TypeSystemHolder typeSystemHolder)
    {
        for (int i = 0; i < instances.length; i++)
        {
            XmlObject instance = instances[i];
            XmlCursor xc = instance.newCursor();
            // xc on start doc

            StringBuilder comment = new StringBuilder();

            while( !xc.isStart() )
            {
                xc.toNextToken();
                if( xc.isComment() )
                    comment.append(xc.getTextValue());
                else if (xc.isEnddoc())
                    return;
            }
            // xc now on the root element

            Element withElem = processElement(xc, comment.toString(), options, typeSystemHolder);
            withElem.setGlobal(true);

            addGlobalElement(withElem, typeSystemHolder, options);
        }
    }

    protected Element addGlobalElement(Element withElem, TypeSystemHolder typeSystemHolder, Inst2XsdOptions options)
    {
        assert withElem.isGlobal();
        Element intoElem = typeSystemHolder.getGlobalElement(withElem.getName());

        if (intoElem==null)
        {
            typeSystemHolder.addGlobalElement(withElem);
            return withElem;
        }
        else
        {
            combineTypes(intoElem.getType(), withElem.getType(), options);
            combineElementComments(intoElem, withElem);
            return intoElem;
        }
    }

    protected Element processElement(XmlCursor xc, String comment,
        Inst2XsdOptions options, TypeSystemHolder typeSystemHolder)
    {
        assert xc.isStart();
        Element element = new Element();
        element.setName(xc.getName());
        element.setGlobal(false);

        Type elemType = Type.createUnnamedType(Type.SIMPLE_TYPE_SIMPLE_CONTENT); //assume simple, set later
        element.setType(elemType);

        StringBuilder textBuff = new StringBuilder();
        StringBuilder commentBuff = new StringBuilder();
        List children = new ArrayList();
        List attributes = new ArrayList();

        loop: do
        {
            XmlCursor.TokenType tt = xc.toNextToken();
            switch (tt.intValue())
            {
                case XmlCursor.TokenType.INT_ATTR:
                    // todo check for xsi:type
                    // ignore xsi:... attributes other than xsi:nil
                    QName attName = xc.getName();
                    if (!_xsiNil.getNamespaceURI().equals(attName.getNamespaceURI()))
                        attributes.add(processAttribute(xc, options, element.getName().getNamespaceURI(), typeSystemHolder));
                    else if (_xsiNil.equals(attName))
                        element.setNillable(true);

                    break;

                case XmlCursor.TokenType.INT_START:
                    children.add(processElement(xc, commentBuff.toString(), options, typeSystemHolder));
                    commentBuff.delete(0, commentBuff.length());
                    break;

                case XmlCursor.TokenType.INT_TEXT:
                    textBuff.append(xc.getChars());
                    break;

                case XmlCursor.TokenType.INT_COMMENT:
                    commentBuff.append(xc.getTextValue());
                    break;

                case XmlCursor.TokenType.INT_NAMESPACE:
                    // ignore,
                    // each element and attribute will take care to define itself in the right targetNamespace
                    break;

                case XmlCursor.TokenType.INT_END:
                    break loop;

                case XmlCursor.TokenType.INT_PROCINST:
                    // ignore
                    break;

                case XmlCursor.TokenType.INT_ENDDOC:
                    break loop;

                case XmlCursor.TokenType.INT_NONE:
                    break loop;

                case XmlCursor.TokenType.INT_STARTDOC:
                    throw new IllegalStateException();

                default:
                    throw new IllegalStateException("Unknown TokenType.");
            }
        }
        while( true );

        String collapsedText =  XmlWhitespace.collapse(textBuff.toString(), XmlWhitespace.WS_COLLAPSE);

        String commnetStr = (comment == null ?
            ( commentBuff.length() == 0 ? null : commentBuff.toString() ) :
            ( commentBuff.length() == 0 ? comment : commentBuff.insert(0, comment).toString()) );
        element.setComment(commnetStr);

        if (children.size()>0)
        {
            // complex content
            if (collapsedText.length()>0)
            {
                elemType.setContentType(Type.COMPLEX_TYPE_MIXED_CONTENT);
            }
            else
            {
                elemType.setContentType(Type.COMPLEX_TYPE_COMPLEX_CONTENT);
            }
            processElementsInComplexType(elemType, children, element.getName().getNamespaceURI(), typeSystemHolder, options);
            processAttributesInComplexType(elemType, attributes);
        }
        else
        {
            // simple content
            // hack workaround for being able to call xc.getNamespaceForPrefix()
            XmlCursor xcForNamespaces = xc.newCursor();
            xcForNamespaces.toParent();

            if (attributes.size()>0)
            {
                elemType.setContentType(Type.COMPLEX_TYPE_SIMPLE_CONTENT);

                Type extendedType = Type.createNamedType(
                    processSimpleContentType(textBuff.toString(), options, xcForNamespaces), Type.SIMPLE_TYPE_SIMPLE_CONTENT);
                elemType.setExtensionType(extendedType);

                processAttributesInComplexType(elemType, attributes);
            }
            else
            {
                elemType.setContentType(Type.SIMPLE_TYPE_SIMPLE_CONTENT);
                elemType.setName(processSimpleContentType(textBuff.toString(), options, xcForNamespaces));

                // add enumeration value
                String enumValue = XmlString.type.getName().equals(elemType.getName()) ? textBuff.toString() : collapsedText;
                elemType.addEnumerationValue(enumValue, xcForNamespaces);
            }

            xcForNamespaces.dispose(); // end hack
        }

        checkIfReferenceToGlobalTypeIsNeeded( element, typeSystemHolder, options);

        return element;
    }

    protected void processElementsInComplexType(Type elemType, List children, String parentNamespace,
        TypeSystemHolder typeSystemHolder, Inst2XsdOptions options)
    {
        Map elemNamesToElements = new HashMap();
        Element currentElem = null;

        for (Iterator iterator = children.iterator(); iterator.hasNext();)
        {
            Element child = (Element) iterator.next();

            if (currentElem==null)
            {   // first element in this type
                checkIfElementReferenceIsNeeded(child, parentNamespace, typeSystemHolder, options);
                elemType.addElement(child);
                elemNamesToElements.put(child.getName(), child);
                currentElem = child;
                continue;
            }

            if (currentElem.getName()==child.getName())
            {   // same contiguos element
                combineTypes(currentElem.getType(), child.getType(), options); // unify types
                combineElementComments(currentElem, child);
                // minOcc=0 maxOcc=unbounded
                currentElem.setMinOccurs(0);
                currentElem.setMaxOccurs(Element.UNBOUNDED);
            }
            else
            {
                Element sameElem = (Element)elemNamesToElements.get(child.getName());
                if (sameElem==null)
                {   // new element name
                    checkIfElementReferenceIsNeeded(child, parentNamespace, typeSystemHolder, options);
                    elemType.addElement(child);
                    elemNamesToElements.put(child.getName(), child);
                }
                else
                {   //same non contiguos
                    combineTypes(currentElem.getType(), child.getType(), options);
                    combineElementComments(currentElem, child);
                    elemType.setTopParticleForComplexOrMixedContent(Type.PARTICLE_CHOICE_UNBOUNDED);
                }
                currentElem = child;
            }
        }
    }

    protected void checkIfElementReferenceIsNeeded(Element child, String parentNamespace,
        TypeSystemHolder typeSystemHolder, Inst2XsdOptions options)
    {
        if (!child.getName().getNamespaceURI().equals(parentNamespace))
        {
            Element referencedElem = new Element();
            referencedElem.setGlobal(true);
            referencedElem.setName(child.getName());
            referencedElem.setType(child.getType());

            if (child.isNillable())
            {
                referencedElem.setNillable(true);
                child.setNillable(false);
            }

            referencedElem = addGlobalElement(referencedElem, typeSystemHolder, options);

            child.setRef(referencedElem); // clears child's type
        }
    }

    protected void checkIfReferenceToGlobalTypeIsNeeded(Element elem, TypeSystemHolder typeSystemHolder,
        Inst2XsdOptions options)
    {
        // RussianDollDesign doesn't define global types
    }

    protected void processAttributesInComplexType(Type elemType, List attributes)
    {
        assert elemType.isComplexType();
        for (Iterator iterator = attributes.iterator(); iterator.hasNext();)
        {
            Attribute att = (Attribute) iterator.next();
            elemType.addAttribute(att);
        }
    }

    protected Attribute processAttribute(XmlCursor xc, Inst2XsdOptions options, String parentNamespace,
                                              TypeSystemHolder typeSystemHolder)
    {
        assert xc.isAttr() : "xc not on attribute";
        Attribute attribute = new Attribute();
        QName attName = xc.getName();

        attribute.setName(attName);

        XmlCursor parent = xc.newCursor();
        parent.toParent();

        Type simpleContentType = Type.createNamedType(
            processSimpleContentType(xc.getTextValue(), options, parent), Type.SIMPLE_TYPE_SIMPLE_CONTENT);

        parent.dispose();

        attribute.setType(simpleContentType);

        checkIfAttributeReferenceIsNeeded(attribute, parentNamespace, typeSystemHolder);

        return attribute;
    }

    protected void checkIfAttributeReferenceIsNeeded(Attribute attribute, String parentNamespace, TypeSystemHolder typeSystemHolder)
    {
        if (!attribute.getName().getNamespaceURI().equals("") &&
            !attribute.getName().getNamespaceURI().equals(parentNamespace))
        {
            // make attribute be a reference to a top level attribute in a different targetNamespace
            Attribute referencedAtt = new Attribute();
            referencedAtt.setGlobal(true);
            referencedAtt.setName(attribute.getName());
            referencedAtt.setType(attribute.getType());

            typeSystemHolder.addGlobalAttribute(referencedAtt);

            attribute.setRef(referencedAtt);
        }
    }

    protected class SCTValidationContext
        implements ValidationContext
    {
        protected boolean valid = true;

        public boolean isValid()
        {
            return valid;
        }

        public void resetToValid()
        {
            valid = true;
        }

        public void invalid(String message)
        {
            valid = false;
        }

        public void invalid(String code, Object[] args)
        {
            valid = false;
        }
    }

    private SCTValidationContext _validationContext = new SCTValidationContext();


    // List of precedence for smart simple primitive type determination
    // byte, short, int, long, integer, float, double, decimal,
    // boolean
    // date, dateTime, time, gDuration,
    // QName ?,
    // anyUri ? - triggered only for http:// or www. constructs,
    // list types ?
    // string
    protected QName processSimpleContentType(String lexicalValue, Inst2XsdOptions options, final XmlCursor xc)
    {
        // check options and return xsd:string or if smart is enabled, look for a better type
        if (options.getSimpleContentTypes()==Inst2XsdOptions.SIMPLE_CONTENT_TYPES_STRING)
            return XmlString.type.getName();

        if (options.getSimpleContentTypes()!=Inst2XsdOptions.SIMPLE_CONTENT_TYPES_SMART)
            throw new IllegalArgumentException("Unknown value for Inst2XsdOptions.getSimpleContentTypes() :" + options.getSimpleContentTypes());

        // Inst2XsdOptions.SIMPLE_CONTENT_TYPES_SMART case


        try
        {
            XsTypeConverter.lexByte(lexicalValue);
            return XmlByte.type.getName();
        }
        catch (Exception e) {}

        try
        {
            XsTypeConverter.lexShort(lexicalValue);
            return XmlShort.type.getName();
        }
        catch (Exception e) {}

        try
        {
            XsTypeConverter.lexInt(lexicalValue);
            return XmlInt.type.getName();
        }
        catch (Exception e) {}

        try
        {
            XsTypeConverter.lexLong(lexicalValue);
            return XmlLong.type.getName();
        }
        catch (Exception e) {}

        try
        {
            XsTypeConverter.lexInteger(lexicalValue);
            return XmlInteger.type.getName();
        }
        catch (Exception e) {}

        try
        {
            XsTypeConverter.lexFloat(lexicalValue);
            return XmlFloat.type.getName();
        }
        catch (Exception e) {}

//        // this not needed because it's lexical space is covered by float
//        try
//        {
//            XsTypeConverter.lexDouble(lexicalValue);
//            return XmlDouble.type.getName();
//        }
//        catch (Exception e) {}
//
//        try
//        {
//            XsTypeConverter.lexDecimal(lexicalValue);
//            return XmlDecimal.type.getName();
//        }
//        catch (Exception e) {}

        XmlDateImpl.validateLexical(lexicalValue, XmlDate.type, _validationContext);
        if (_validationContext.isValid())
            return XmlDate.type.getName();
        _validationContext.resetToValid();

        XmlDateTimeImpl.validateLexical(lexicalValue, XmlDateTime.type, _validationContext);
        if (_validationContext.isValid())
            return XmlDateTime.type.getName();
        _validationContext.resetToValid();

        XmlTimeImpl.validateLexical(lexicalValue, XmlTime.type, _validationContext);
        if (_validationContext.isValid())
            return XmlTime.type.getName();
        _validationContext.resetToValid();

        XmlDurationImpl.validateLexical(lexicalValue, XmlDuration.type, _validationContext);
        if (_validationContext.isValid())
            return XmlDuration.type.getName();
        _validationContext.resetToValid();

        // check for uri
        if (lexicalValue.startsWith("http://") || lexicalValue.startsWith("www."))
        {
            XmlAnyUriImpl.validateLexical(lexicalValue, _validationContext);
            if (_validationContext.isValid())
                return XmlAnyURI.type.getName();
            _validationContext.resetToValid();
        }

        // check for QName
        int idx = lexicalValue.indexOf(':');
        if (idx>=0 && idx==lexicalValue.lastIndexOf(':') && idx+1<lexicalValue.length())
        {
            PrefixResolver prefixResolver = new PrefixResolver()
            {
                public String getNamespaceForPrefix(String prefix)
                {  return xc.namespaceForPrefix(prefix); }
            };

            QName qname = XmlQNameImpl.validateLexical(lexicalValue, _validationContext, prefixResolver);
            if (_validationContext.isValid())
                return XmlQName.type.getName();
            _validationContext.resetToValid();
        }

        //the check for lists is probably too expensive

        return XmlString.type.getName();
    }


    protected void combineTypes(Type into, Type with, Inst2XsdOptions options)
    {
        if (into==with)
            return;

        if (into.isGlobal() && with.isGlobal() && into.getName().equals(with.getName()))
            return;


        if (into.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT &&
            with.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT)
        {
            combineSimpleTypes(into, with, options);
            return;
        }

        if ((into.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT ||
            into.getContentType()==Type.COMPLEX_TYPE_SIMPLE_CONTENT) &&
            (with.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT ||
            with.getContentType()==Type.COMPLEX_TYPE_SIMPLE_CONTENT) )
        {
            // take the extension name if it's a complex type
            QName intoTypeName = into.isComplexType() ? into.getExtensionType().getName() : into.getName();
            QName withTypeName = with.isComplexType() ? with.getExtensionType().getName() : with.getName();

            //complex type simple content
            into.setContentType(Type.COMPLEX_TYPE_SIMPLE_CONTENT);

            QName moreGeneralTypeName = combineToMoreGeneralSimpleType(intoTypeName, withTypeName);
            if (into.isComplexType())
            {
                Type extendedType = Type.createNamedType(moreGeneralTypeName, Type.SIMPLE_TYPE_SIMPLE_CONTENT);
                into.setExtensionType(extendedType);
            }
            else
                into.setName(moreGeneralTypeName);

            combineAttributesOfTypes(into, with);
            return;
        }

        if (into.getContentType()==Type.COMPLEX_TYPE_COMPLEX_CONTENT &&
            with.getContentType()==Type.COMPLEX_TYPE_COMPLEX_CONTENT)
        {
            combineAttributesOfTypes(into, with);
            combineElementsOfTypes(into, with, false, options);
            return;
        }

        if (into.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT ||
            into.getContentType()==Type.COMPLEX_TYPE_SIMPLE_CONTENT ||
            with.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT ||
            with.getContentType()==Type.COMPLEX_TYPE_SIMPLE_CONTENT)
        {
            into.setContentType(Type.COMPLEX_TYPE_MIXED_CONTENT);
            combineAttributesOfTypes(into, with);
            combineElementsOfTypes(into, with, true, options);
            return;
        }

        if ((into.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT ||
            into.getContentType()==Type.COMPLEX_TYPE_SIMPLE_CONTENT ||
            into.getContentType()==Type.COMPLEX_TYPE_COMPLEX_CONTENT ||
            into.getContentType()==Type.COMPLEX_TYPE_MIXED_CONTENT) &&
            (with.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT ||
            with.getContentType()==Type.COMPLEX_TYPE_SIMPLE_CONTENT ||
            with.getContentType()==Type.COMPLEX_TYPE_COMPLEX_CONTENT ||
            with.getContentType()==Type.COMPLEX_TYPE_MIXED_CONTENT) )
        {
            into.setContentType(Type.COMPLEX_TYPE_MIXED_CONTENT);
            combineAttributesOfTypes(into, with);
            combineElementsOfTypes(into, with, false, options);
            return;
        }

        throw new IllegalArgumentException("Unknown content type.");
    }

    protected void combineSimpleTypes(Type into, Type with, Inst2XsdOptions options)
    {
        assert (into.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT &&
            with.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT) : "Invalid arguments";

        //simple type simple content
        into.setName(combineToMoreGeneralSimpleType(into.getName(), with.getName()));

        // take care of enumeration values
        if (options.isUseEnumerations())
        {
            into.addAllEnumerationsFrom(with);

            if (into.getEnumerationValues().size()>options.getUseEnumerations())
            {
                into.closeEnumeration();
            }
        }
    }

    protected QName combineToMoreGeneralSimpleType(QName t1, QName t2)
    {
        if (t1.equals(t2))
            return t1;

        if (t2.equals(XmlShort.type.getName()) && t1.equals(XmlByte.type.getName()))
            return t2;
        if (t1.equals(XmlShort.type.getName()) && t2.equals(XmlByte.type.getName()))
            return t1;

        if (t2.equals(XmlInt.type.getName()) &&
            (t1.equals(XmlShort.type.getName()) || t1.equals(XmlByte.type.getName())) )
            return t2;
        if (t1.equals(XmlInt.type.getName()) &&
            (t2.equals(XmlShort.type.getName()) || t2.equals(XmlByte.type.getName())) )
            return t1;

        if (t2.equals(XmlLong.type.getName()) &&
            (t1.equals(XmlInt.type.getName()) || t1.equals(XmlShort.type.getName()) || t1.equals(XmlByte.type.getName())) )
            return t2;
        if (t1.equals(XmlLong.type.getName()) &&
            (t2.equals(XmlInt.type.getName()) || t2.equals(XmlShort.type.getName()) || t2.equals(XmlByte.type.getName())) )
            return t1;

        if (t2.equals(XmlInteger.type.getName()) &&
            (t1.equals(XmlLong.type.getName()) || t1.equals(XmlInt.type.getName()) ||
            t1.equals(XmlShort.type.getName()) || t1.equals(XmlByte.type.getName())) )
            return t2;
        if (t1.equals(XmlInteger.type.getName()) &&
            (t2.equals(XmlLong.type.getName()) || t2.equals(XmlInt.type.getName()) ||
            t2.equals(XmlShort.type.getName()) || t2.equals(XmlByte.type.getName())) )
            return t1;

        if (t2.equals(XmlFloat.type.getName()) &&
            (t1.equals(XmlInteger.type.getName()) ||
            t1.equals(XmlLong.type.getName()) || t1.equals(XmlInt.type.getName()) ||
            t1.equals(XmlShort.type.getName()) || t1.equals(XmlByte.type.getName())) )
            return t2;
        if (t1.equals(XmlFloat.type.getName()) &&
            (t2.equals(XmlInteger.type.getName()) ||
            t2.equals(XmlLong.type.getName()) || t2.equals(XmlInt.type.getName()) ||
            t2.equals(XmlShort.type.getName()) || t2.equals(XmlByte.type.getName())) )
            return t1;

        //double, decimal will never get here since they don't get generated

        //the rest of the combinations are not compatible, so they will combine in xsd:string
        return XmlString.type.getName();
    }

    protected void combineAttributesOfTypes(Type into, Type from)
    {
        // loop through attributes: add fromAtt if they don't exist, combine them if they exist
        outterLoop:
        for (int i = 0; i < from.getAttributes().size(); i++)
        {
            Attribute fromAtt = (Attribute)from.getAttributes().get(i);
            for (int j = 0; j < into.getAttributes().size(); j++)
            {
                Attribute intoAtt = (Attribute)into.getAttributes().get(j);
                if (intoAtt.getName().equals(fromAtt.getName()))
                {
                    intoAtt.getType().setName(
                        combineToMoreGeneralSimpleType(intoAtt.getType().getName(), fromAtt.getType().getName()));
                    continue outterLoop;
                }
            }
            // fromAtt doesn't exist in into type, will add it right now
            into.addAttribute(fromAtt);
        }

        //optional attributes: if there are atts in into that are not in from, make them optional
        outterLoop:
        for (int i = 0; i < into.getAttributes().size(); i++)
        {
            Attribute intoAtt = (Attribute)into.getAttributes().get(i);
            for (int j = 0; j < from.getAttributes().size(); j++)
            {
                Attribute fromAtt = (Attribute)from.getAttributes().get(j);
                if (fromAtt.getName().equals(intoAtt.getName()))
                {
                    continue;
                }
            }
            // intoAtt doesn't exist in into type, will add it right now
            intoAtt.setOptional(true);
        }
    }

    protected void combineElementsOfTypes(Type into, Type from, boolean makeElementsOptional, Inst2XsdOptions options)
    {
        boolean needsUnboundedChoice = false;

        if (into.getTopParticleForComplexOrMixedContent()!=Type.PARTICLE_SEQUENCE ||
            from.getTopParticleForComplexOrMixedContent()!=Type.PARTICLE_SEQUENCE)
            needsUnboundedChoice = true;

        List res = new ArrayList();

        int fromStartingIndex = 0;
        int fromMatchedIndex = -1;
        int intoMatchedIndex = -1;

        // for each element in into
        for (int i = 0; !needsUnboundedChoice && i < into.getElements().size(); i++)
        {
            // try to find one with same name in from
            Element intoElement = (Element) into.getElements().get(i);
            for (int j = fromStartingIndex; j < from.getElements().size(); j++)
            {
                Element fromElement = (Element) from.getElements().get(j);
                if (intoElement.getName().equals(fromElement.getName()))
                {
                    fromMatchedIndex = j;
                    break;
                }
            }

            // if not found, it's safe to add this one to result 'res' (as optional) and continue
            if ( fromMatchedIndex < fromStartingIndex )
            {
                res.add(intoElement);
                intoElement.setMinOccurs(0);
                continue;
            }

            // else try out all from elemens between fromStartingIndex to fromMatchedIndex
            // to see if they match one of the into elements
            intoMatchingLoop:
            for (int j2 = fromStartingIndex; j2 < fromMatchedIndex; j2++)
            {
                Element fromCandidate = (Element) from.getElements().get(j2);

                for (int i2 = i+1; i2 < into.getElements().size(); i2++)
                {
                    Element intoCandidate = (Element) into.getElements().get(i2);
                    if (fromCandidate.getName().equals(intoCandidate.getName()))
                    {
                        intoMatchedIndex = i2;
                        break intoMatchingLoop;
                    }
                }
            }

            if (intoMatchedIndex<i)
            {
                // if none matched they are safe to be added to res as optional
                for (int j3 = fromStartingIndex; j3 < fromMatchedIndex; j3++)
                {
                    Element fromCandidate = (Element) from.getElements().get(j3);
                    res.add(fromCandidate);
                    fromCandidate.setMinOccurs(0);
                }
                // also since into[i] == from[fromMatchedIndex] add it only once
                res.add(intoElement);
                Element fromMatchedElement = (Element)from.getElements().get(fromMatchedIndex);

                if (fromMatchedElement.getMinOccurs()<=0)
                    intoElement.setMinOccurs(0);
                if (fromMatchedElement.getMaxOccurs()==Element.UNBOUNDED)
                    intoElement.setMaxOccurs(Element.UNBOUNDED);

                combineTypes(intoElement.getType(), fromMatchedElement.getType(), options);
                combineElementComments(intoElement, fromMatchedElement);

                fromStartingIndex = fromMatchedIndex + 1;
                continue;
            }
            else
            {
                // if matched it means into type will transform into a choice unbounded type
                needsUnboundedChoice = true;
            }
        }

        for (int j = fromStartingIndex; j < from.getElements().size(); j++)
        {
            Element remainingFromElement = (Element) from.getElements().get(j);
            res.add(remainingFromElement);
            remainingFromElement.setMinOccurs(0);
        }

        // if choice was detected
        if (needsUnboundedChoice)
        {
            into.setTopParticleForComplexOrMixedContent(Type.PARTICLE_CHOICE_UNBOUNDED);

            outterLoop:
            for (int j = 0; j < from.getElements().size(); j++)
            {
                Element fromElem = (Element) from.getElements().get(j);
                for (int i = 0; i < into.getElements().size(); i++)
                {
                    Element intoElem = (Element)into.getElements().get(i);
                    intoElem.setMinOccurs(1);
                    intoElem.setMaxOccurs(1);

                    if (intoElem==fromElem)
                        continue outterLoop;

                    if (intoElem.getName().equals(fromElem.getName()))
                    {
                        combineTypes(intoElem.getType(), fromElem.getType(), options);
                        combineElementComments(intoElem, fromElem);

                        continue outterLoop;
                    }
                }

                // fromElem doesn't exist in into type, will add it right now
                into.addElement(fromElem);
                fromElem.setMinOccurs(1);
                fromElem.setMaxOccurs(1);
            }
            return;
        }
        else
        {
            // into remains sequence but will contain the new list of elements res
            into.setElements(res);
            return;
        }
    }

    protected void combineElementComments(Element into, Element with)
    {
        if (with.getComment()!=null && with.getComment().length()>0)
        {
            if (into.getComment()==null)
                into.setComment(with.getComment());
            else
                into.setComment(into.getComment() + with.getComment());
        }
    }
}
