package com.jxml.quick.util.qjml2java;
import com.jxml.quick.model.qjml.*;
import com.jxml.quick.*;
import org.xml.sax.*;
import java.util.*;
import com.jxml.quick.ocm.*;
import java.io.*;

/**
 * Extracts QJML data.
 */
public class QCAbstract extends OCMpeerSupport {
    /**
     * User-provided code to perform the conversion.
     */
    public void cvt(Object param) throws SAXException, IOException {
	QMAbstract ed=(QMAbstract)dataModel;
        //System.out.println("QCAbstract " + ed.getLabel());
	Conv.SubConv conv=(Conv.SubConv)context;
        conv.done.put(ed.getLabel(), ed);
        //String targetClass = Element.getTargetText(ed.targetClass);
        String targetClass = ed.getClassName();
	addStringAttribute("ID",ed.getLabel());
	addStringAttribute("targetClass",targetClass);
	addStringAttribute("tagName",ed.label);
        // textConstructor is false (default value)
        addBooleanAttribute("newClass",ed.generate);
	addBooleanAttribute("hasAClass",!Element.isJavaType(targetClass));
        // clonable is true (default value)
        // wild is false (default value)
        // bimodal is false (default value);
	addBooleanAttribute("abst",true);
        // intf is false (default value)
	addBooleanAttribute("generate",ed.generate);

	startElement("element");
        
        // making parentElement
        QMExtends ext = ed.extendor;
        if (ext != null) {
            String name = ext.getQText();
            if (conv.done.get(name) == null) {
                QMCoin coin = (QMCoin)conv.coinMap.get(name);
                doCvt(coin,null);
            } else {
	        addStringAttribute("href","#"+name);
	        emptyElement("link");
            }
        }

        // imp
        if (ed.implementsList.size() > 0) {
	    startElement("imp");
            for (int i=0; i<ed.implementsList.size(); i++) {
                String name = ((QMImplements)ed.implementsList.get(i)).text;
                if (conv.done.get(name) == null)
                    doCvt(conv.coinMap.get(name),null);
                else {
	            addStringAttribute("href","#"+name);
	            emptyElement("link");
                }
            }
	    endElement("imp");
        }

        // subclasses
        if (ed.extensions != null && ed.extensions.size() > 0) {
	    startElement("subclasses");
            for (int i=0; i<ed.extensions.size(); i++) {
                QMCoin coin = (QMCoin)ed.extensions.get(i);
                String name = coin.getLabel();
                if (conv.done.get(name) == null)
                    doCvt(coin,null);
                else {
	            addStringAttribute("href","#"+name);
	            emptyElement("link");
                }
            }
	    endElement("subclasses");
        }
        
    	doCvt(ed.attributes,null);
        
        // no child elements in abstract
        
        doCvt(ed.validList,null);

    	doCvt(ed.remList,null);

        if ((ed.fieldList != null && ed.fieldList.size() > 0) ||
            (ed.propertyList != null && ed.propertyList.size() > 0))
	    startElement("fields");
        
        // other fields
        if (ed.fieldList != null && ed.fieldList.size() > 0) {
            for (int i=0; i<ed.fieldList.size(); i++) {
                QMField field = (QMField)ed.fieldList.get(i);
                addOtherField(this, field);
            }
        }
        
        // other properties
        if (ed.propertyList != null && ed.propertyList.size() > 0) {
            for (int i=0; i<ed.propertyList.size(); i++) {
                QMProperty prop = (QMProperty)ed.propertyList.get(i);
                addOtherProperty(this, prop);
            }
        }
        if ((ed.fieldList != null && ed.fieldList.size() > 0) ||
            (ed.propertyList != null && ed.propertyList.size() > 0))        
	    endElement("fields");
        
        endElement("element");
    }
    
    public static void addOtherField(OCMpeerSupport ops, QMField field) throws SAXException {
        ops.addStringAttribute("fieldName",field.name);
        
        if (field.mCoin != null) {
            if ("list".equals(field.kind))
                ops.addStringAttribute("targetClass", "java.util.ArrayList");
            else
                ops.addStringAttribute("targetClass", field.mCoin.getClassName());
            //if (!(field.mCoin.getTarget() instanceof QMTargetClass))
            boolean newClass;
            if ("list".equals(field.kind) ||
                field.mCoin.getClassName().startsWith("java.lang"))
                newClass = false;
            else
                newClass = field.mCoin.generate;
            ops.addBooleanAttribute("newClass",newClass);
            boolean hasAClass = !Element.isJavaType(field.mCoin.getClassName());
            ops.addBooleanAttribute("hasAClass", hasAClass);
            if (!("list".equals(field.kind)) && !newClass &&
                field.mCoin.remList != null && field.mCoin.remList.size() > 0) {
                String nl = System.getProperty("line.separator");
                String comment = null;
                for (int j=0; j<field.mCoin.remList.size(); j++) {
                    if (comment != null)
                        comment += nl;
                    else
                        comment = "";
                    comment += ((QMRem)field.mCoin.remList.get(j)).getQText();
                }
                ops.addStringAttribute("comment", comment);
            } else if ("list".equals(field.kind))
                ops.addStringAttribute("comment", "list of " + field.mCoin.getClassName());
            if ("list".equals(field.kind)) {
                ops.addBooleanAttribute("typedList", true);
                ops.addStringAttribute("childClass", field.mCoin.getClassName());
                ops.addBooleanAttribute("childNewClass", field.mCoin.generate);
                String tag = null;
                if (field.mCoin instanceof QMBean)
                    tag = ((QMBean)field.mCoin).tag;
                else if (field.mCoin instanceof QMText)
                    tag = ((QMText)field.mCoin).tag;
                else if (field.mCoin instanceof QMLink)
                    tag = ((QMLink)field.mCoin).tag;
                if (tag != null)
                    ops.addStringAttribute("childName", tag);
                ops.startElement("field");
                ops.startElement("children");
                ops.addStringAttribute("href","#"+field.mCoin.getLabel());
                ops.emptyElement("link");
                ops.endElement("children");
                ops.endElement("field");
            } else
                ops.emptyElement("field");
        } else if ("list".equals(field.kind)) {
            ops.addStringAttribute("targetClass","java.util.List");
            ops.emptyElement("field");
        } else {
            ops.addBooleanAttribute("newClass", false);
            ops.emptyElement("field");
        }
    }
    
    public static void addOtherProperty(OCMpeerSupport ops, QMProperty prop) throws SAXException {
        ops.addStringAttribute("fieldName",prop.name);
        ops.addBooleanAttribute("property",true);
        
        if (prop.mCoin != null) {
            if ("list".equals(prop.kind))
                ops.addStringAttribute("targetClass", "java.util.ArrayList");
            else
                ops.addStringAttribute("targetClass", prop.mCoin.getClassName());
            boolean newClass;
            if ("list".equals(prop.kind) ||
                prop.mCoin.getClassName().startsWith("java.lang"))
                newClass = false;
            else
                newClass = prop.mCoin.generate;
            ops.addBooleanAttribute("newClass", newClass);
            ops.addBooleanAttribute("hasAClass", !Element.isJavaType(prop.mCoin.getClassName()));
            if (!("list".equals(prop.kind)) && !newClass &&
                prop.mCoin.remList != null && prop.mCoin.remList.size() > 0) {
                String nl = System.getProperty("line.separator");
                String comment = null;
                for (int j=0; j<prop.mCoin.remList.size(); j++) {
                    if (comment != null)
                        comment += nl;
                    else
                        comment = "";
                    comment += ((QMRem)prop.mCoin.remList.get(j)).getQText();
                }
                ops.addStringAttribute("comment", comment);
            } else if ("list".equals(prop.kind))
                ops.addStringAttribute("comment", "list of " + prop.mCoin.getClassName());
            if ("list".equals(prop.kind)) {
                ops.addBooleanAttribute("typedList", true);
                ops.addStringAttribute("childClass", prop.mCoin.getClassName());
                ops.addBooleanAttribute("childNewClass", prop.mCoin.generate);
                String tag = null;
                if (prop.mCoin instanceof QMBean)
                    tag = ((QMBean)prop.mCoin).tag;
                else if (prop.mCoin instanceof QMText)
                    tag = ((QMText)prop.mCoin).tag;
                else if (prop.mCoin instanceof QMLink)
                    tag = ((QMLink)prop.mCoin).tag;
                if (tag != null)
                    ops.addStringAttribute("childName", tag);
                ops.startElement("field");
                ops.startElement("children");
                ops.addStringAttribute("href","#"+prop.mCoin.getLabel());
                ops.emptyElement("link");
                ops.endElement("children");
                ops.endElement("field");
            } else
                ops.emptyElement("field");
        } else if ("list".equals(prop.kind)) {
            ops.addStringAttribute("targetClass","java.util.List");
            ops.emptyElement("field");
        } else {
            ops.addBooleanAttribute("newClass", false);
            ops.emptyElement("field");
        }
    }
}
