/*-------------------------------------------------------------------------------
Copyright (c)2000 TogetherSoft Corporation. Patents pending. All rights reserved.
-------------------------------------------------------------------------------*/

package com.togethersoft.modules.patterns.UNIVERSAL.CLASS.GoF.Factory_Method;

import java.util.Enumeration;
import java.util.Vector;

import com.togethersoft.openapi.sci.*;
import com.togethersoft.openapi.sci.enum.*;

import com.togethersoft.openapi.sci.pattern.SciPattern;
import com.togethersoft.openapi.sci.pattern.SciPatternUtil;

import com.togethersoft.openapi.util.propertyMap.Property;
import com.togethersoft.openapi.util.propertyMap.PropertyMapEvent;
import com.togethersoft.openapi.util.propertyMap.PropertyMapListener;
import com.togethersoft.openapi.util.propertyMap.PropertyMapAdapter;

import com.togethersoft.openapi.ide.message.IdeMessageManagerAccess;
import com.togethersoft.openapi.ide.message.IdeMessageType;

import com.togethersoft.modules.patterns.UNIVERSAL.CLASS.ClassPatternBase;
import com.togethersoft.modules.patterns.UNIVERSAL.PatternBaseException;
import com.togethersoft.modules.patterns.UNIVERSAL.PatternUIBuilder;

/**
 * GoF Factory Method pattern.
 * @author TogetherSoft
 */
public class Pattern extends ClassPatternBase implements SciPattern {

    private static final String PATTERN_NAME = "Factory Method";

    public Pattern() {
        setPatternDisplayName(PATTERN_NAME);

        // Initialize PropertyMap
        setPropertyValue(SELECTED_CLASS_ROLE, null);
        setPropertyValue(PRODUCT, PRODUCT);
        setPropertyValue(CREATOR, CREATOR);
        setPropertyValue(FACTORY_METHOD_NAME, FACTORY_METHOD);
        setPropertyValue(FACTORY_METHOD_PARAMETERS, DEFAULT_PARAMETER_SET);
        setPropertyValue(CONCRETE_PRODUCT, null);
        setPropertyValue(CONCRETE_CREATOR, null);
        setPropertyValue(EXPORT_DOCUMENTATION, Boolean.FALSE);
        setPropertyValue(CREATE_PATTERN_LINKS, Boolean.TRUE);
    }

    protected void finalize() throws Throwable {
        super.finalize();

        if (myUIBuilder != null) {
            myUIBuilder.removeAllListenedInspectorProperties();
            myUIBuilder = null;
        }

        myClassRoleVector.removeAllElements();
        myClassRoleVector = null;
        myDefaultParameters = null;
    }

    public boolean prepare() {
        try {
            super.prepare();
            notImplementedForIDL();

            // Disable listeners
            myInsideListener = true;

            // Initialize PropertyMap
            setPropertyValue(SELECTED_CLASS_ROLE, null);
            setPropertyValue(PRODUCT, PRODUCT);
            setPropertyValue(CREATOR, CREATOR);
            setPropertyValue(FACTORY_METHOD_NAME, FACTORY_METHOD);

            setPropertyValue(CONCRETE_PRODUCT, null);
            setPropertyValue(CONCRETE_CREATOR, null);
            setPropertyValue(FACTORY_METHOD_PARAMETERS, DEFAULT_PARAMETER_SET);

            myClassRoleVector.removeAllElements();

            if (getSelectedClass() == null) {
                addPropertyValue(CONCRETE_PRODUCT, "ConcreteProduct");
                addPropertyValue(CONCRETE_CREATOR, "ConcreteCreator");
            }
            else {
                myClassRoleVector.addElement(PRODUCT);
                myClassRoleVector.addElement(CONCRETE_PRODUCT);
                myClassRoleVector.addElement(CREATOR);
                if (!getSelectedClass().hasProperty(SciProperty.INTERFACE)) {
                    myClassRoleVector.addElement(CONCRETE_CREATOR);
                }

                String  classRole = null;
                if (SciPatternUtil.findPatternLinkSupplier(getSelectedClass(), PATTERN_NAME, PRODUCT) != null) {
                    if (SciPatternUtil.findExtendedPatternLinkClient(getSelectedClass(), PATTERN_NAME, CONCRETE_CREATOR) != null) {
                        classRole = CONCRETE_CREATOR;
                        addPropertyValue(CONCRETE_CREATOR, getSelectedClass().getQualifiedName());
                    }
                    else {
                        classRole = CREATOR;
                        setPropertyValue(CREATOR, getSelectedClass().getQualifiedName());
                    }
                }
                else {
                    if (SciPatternUtil.findExtendedPatternLinkClient(getSelectedClass(), PATTERN_NAME, CONCRETE_PRODUCT) != null) {
                        classRole = CONCRETE_PRODUCT;
                        addPropertyValue(CONCRETE_PRODUCT, getSelectedClass().getQualifiedName());
                    }
                    else {
                        classRole = PRODUCT;
                        setPropertyValue(PRODUCT, getSelectedClass().getQualifiedName());
                    }
                }
                setPropertyValue(SELECTED_CLASS_ROLE, classRole);
            }

            // Enable listeners
            myInsideListener = false;

            if (!initializeInspector()) {
                return false;
            }
            assignActivityResponse();
            return true;
        }
        catch(PatternBaseException e) {
            return false;
        }
    }

    public boolean canApply() {
        try {
            String creatorName = classNameShouldBeCorrect(CREATOR);
            SciClass creatorClass = findClassByName(creatorName);
            shouldBeWritable(CREATOR, creatorClass);

            String productName = classNameShouldBeCorrect(PRODUCT);
            SciClass productClass = findClassByName(productName);

            int numProducts = getNumProperties(CONCRETE_PRODUCT);
            int numCreators = getNumProperties(CONCRETE_CREATOR);

            if (numProducts > numCreators) {
                throw new PatternBaseException(PATTERN_CREATOR_NOT_DEFINED);
            }
            else if (numProducts < numCreators) {
                throw new PatternBaseException(PATTERN_PRODUCT_NOT_DEFINED);
            }

            String concreteCreatorName = null;
            String concreteProductName = null;
            SciClass concreteCreatorClass = null;

            Enumeration creatorsEnum = propertiesEnumeration(CONCRETE_CREATOR);
            Enumeration productsEnum = propertiesEnumeration(CONCRETE_PRODUCT);
            while (creatorsEnum.hasMoreElements() && productsEnum.hasMoreElements()) {
                concreteCreatorName = classNameShouldBeCorrect((Property)creatorsEnum.nextElement());
                concreteCreatorClass = findClassByName(concreteCreatorName);
                shouldBeWritable(CONCRETE_CREATOR, concreteCreatorClass);
                cannotBeAnInterface(CONCRETE_CREATOR, concreteCreatorClass);
                if (creatorClass != null) {
                    shouldExtend(concreteCreatorClass, creatorClass);
                }
                else {
                    shouldExtend(concreteCreatorClass, creatorName);
                }

                concreteProductName = classNameShouldBeCorrect((Property)productsEnum.nextElement());
                SciClass concreteProductClass = findClassByName(concreteProductName);
                shouldBeWritable(CONCRETE_PRODUCT, concreteProductClass);
                if (productClass != null) {
                    shouldExtend(concreteProductClass, productClass);
                }
            }

            String factoryMethod = identifierShouldBeCorrect(FACTORY_METHOD_NAME);
            SciOperation operation = getFactory().newOperation();
            SciParameterList parameterList = operation.getParameterList();
            if (!parameterList.canSetText(getStringPropertyValue(FACTORY_METHOD_PARAMETERS))) {
                throw new PatternBaseException("Incorrect parameter list");
            }

            return true;
        }
        catch(PatternBaseException e) {
            return false;
        }
    }

    public void apply() {
        if (!canApply()) {
            return;
        }
        super.apply();

        myClassRoleVector.removeAllElements();
        myUIBuilder.removeAllListenedInspectorProperties();
        myUIBuilder = null;

        Enumeration creatorsEnum = propertiesEnumeration(CONCRETE_CREATOR);
        Enumeration productsEnum = propertiesEnumeration(CONCRETE_PRODUCT);
        boolean createConcreteClasses = creatorsEnum.hasMoreElements();

/* Get or create Creator class. */

        String creatorName = getStringPropertyValue(CREATOR);
        SciClass creatorClass = getClassByName(creatorName, createConcreteClasses);
        if (createConcreteClasses) {
            creatorClass.setProperty(SciProperty.ABSTRACT, true);
        }

/* Get or create Product class. */

        String productName = getStringPropertyValue(PRODUCT);
        SciClass productClass = getClassByName(productName, createConcreteClasses);
        if (createPatternLinks()) {
            SciPatternUtil.addPatternLink(creatorClass, productClass, PATTERN_NAME, CREATOR, PRODUCT, false);
            SciPatternUtil.addPatternLink(productClass, creatorClass, PATTERN_NAME, null, CREATOR, true);
        }

/* Create Factory Method and constructor. */

        String  factoryMethodName = getStringPropertyValue(FACTORY_METHOD_NAME);
        String  factoryMethodParams = getStringPropertyValue(FACTORY_METHOD_PARAMETERS);

        SciOperation factoryMethod = getFactory().newOperation();
        factoryMethod.setName(factoryMethodName);
        factoryMethod.getParameterList().setText(factoryMethodParams);
        factoryMethod.setProperty(SciProperty.ABSTRACT, createConcreteClasses);
        factoryMethod.getReturnType().setReferencedElement(productClass);
        factoryMethod.setReturnType( getLanguageHelper().makePointerType(factoryMethod.getReturnType()) );
        //factoryMethod.getReturnType().setText( attribute.getType().getCanonicalText() );

        if (SciUtil.findMemberBySignature(creatorClass, factoryMethod) == null) {
            factoryMethod = (SciOperation) creatorClass.paste(factoryMethod, null, false);

            if (!createConcreteClasses) {
                String parameterList = EMPTY_STRING;
                SciParameterEnumeration parameters = factoryMethod.getParameterList().parameters();
                while (parameters.hasMoreElements()) {
                    parameterList += ((SciParameter)parameters.nextElement()).getName();
                    if (parameters.hasMoreElements()) {
                        parameterList += ", ";
                    }
                }

                Object[] arguments = { productClass.getName(), parameterList };
                String body = createTextByPattern(PATTERN_RETURN_NEW, arguments);

                try {
                    factoryMethod.setBody(getGenericFactory().newCodeBlock(body));
                }
                catch(SciGenericFactoryException e) {
                    IdeMessageManagerAccess.printMessage(IdeMessageType.ERROR, CODE_GENERATION_ERROR);
                }
            }
        }

        SciOperation constructor = getFactory().newOperation();
        constructor.setProperty(SciProperty.CONSTRUCTOR, true);
        constructor.getParameterList().setText(getStringPropertyValue(FACTORY_METHOD_PARAMETERS));
        SciPatternUtil.makeStubImplementation(constructor);
        if (!createConcreteClasses && SciUtil.findMemberBySignature(productClass, constructor) == null) {
            productClass.paste(constructor, null, false);
        }

/* Create Concrete Products and Creators. */

        String concreteCreatorName = null;
        String concreteProductName = null;
        while (creatorsEnum.hasMoreElements() && productsEnum.hasMoreElements()) {
            concreteCreatorName = (String)((Property)creatorsEnum.nextElement()).getValue();
            concreteProductName = (String)((Property)productsEnum.nextElement()).getValue();
            if (concreteCreatorName == null || concreteCreatorName.length() == 0 ||
                concreteProductName == null || concreteProductName.length() == 0) {
                continue;
            }

            SciClass concreteCreatorClass = getClassByName(concreteCreatorName, false);
            SciPatternUtil.createInheritance(concreteCreatorClass, creatorClass);
            SciClass concreteProductClass = getClassByName(concreteProductName, false);
            SciPatternUtil.makeStubImplementation(concreteProductClass, productClass, false, exportDocumentation());

            if (createPatternLinks()) {
                SciPatternUtil.addPatternLink(concreteCreatorClass, concreteProductClass, PATTERN_NAME, CREATOR, PRODUCT, false);
                SciPatternUtil.addPatternLink(concreteProductClass, concreteCreatorClass, PATTERN_NAME, null, CREATOR, true);
                SciPatternUtil.addPatternLink(productClass, concreteProductClass, PATTERN_NAME, null, CONCRETE_PRODUCT, false);
                SciPatternUtil.addPatternLink(creatorClass, concreteCreatorClass, PATTERN_NAME, null, CONCRETE_CREATOR, false);
            }

            if (SciUtil.findMemberBySignature(concreteCreatorClass, factoryMethod) == null) {
                SciOperation concreteFactoryMethod = (SciOperation)concreteCreatorClass.paste(factoryMethod, null, false);
                concreteFactoryMethod.setProperty(SciProperty.ABSTRACT, false);
                try {
                    SciParameterEnumeration parameters = concreteFactoryMethod.getParameterList().parameters();
                    String parameterList = EMPTY_STRING;
                    while (parameters.hasMoreElements()) {
                        parameterList += ((SciParameter)parameters.nextElement()).getName();
                        if (parameters.hasMoreElements()) {
                            parameterList += ", ";
                        }
                    }

                    Object[] arguments = { concreteProductClass.getName(), parameterList };
                    String code = createTextByPattern(PATTERN_RETURN_NEW, arguments);

                    concreteFactoryMethod.setBody(getGenericFactory().newCodeBlock(code));
                }
                catch(SciGenericFactoryException e) {
                    IdeMessageManagerAccess.printMessage(IdeMessageType.ERROR, CODE_GENERATION_ERROR);
                }
            }
            if (SciUtil.findMemberBySignature(concreteProductClass, constructor) == null) {
                concreteProductClass.paste(constructor, null, false);
            }
        }
    }

    private void setFactoryMethodParametersCombobox() {
        if (myUIBuilder == null)
            return;

        Vector parameterListsVector = new Vector();

        parameterListsVector.addElement(EMPTY_STRING);
        String productName = getStringPropertyValue(PRODUCT);
        if (productName != null) {
            SciClass product = findClassByName(productName);
            if (product != null) {
                SciOperationEnumeration operations = product.operations();
                while (operations.hasMoreElements()) {
                    SciOperation operation = operations.nextSciOperation();
                    if (operation.hasProperty(SciProperty.CONSTRUCTOR)) {
                        String parameterListString = operation.getParameterList().getText();
                        if (!parameterListsVector.contains(parameterListString)) {
                            parameterListsVector.addElement(parameterListString);
                        }
                    }
                }
            }
        }

        Enumeration concreteProducts = propertiesEnumeration(CONCRETE_PRODUCT);
        while (concreteProducts.hasMoreElements()) {
            String concreteProductName = (String)((Property)concreteProducts.nextElement()).getValue();
            SciClass concreteProduct = findClassByName(concreteProductName);
            if (concreteProduct != null) {
                SciOperationEnumeration operations = concreteProduct.operations();
                while (operations.hasMoreElements()) {
                    SciOperation operation = operations.nextSciOperation();
                    if (operation.hasProperty(SciProperty.CONSTRUCTOR)) {
                        String parameterListString = operation.getParameterList().getText();
                        if (!parameterListsVector.contains(parameterListString)) {
                            parameterListsVector.addElement(parameterListString);
                        }
                    }
                }
            }
        }

        myUIBuilder.setComboBoxItems(FACTORY_METHOD_PARAMETERS, parameterListsVector);
    }

    protected boolean initializeInspector() {
        try {
            myUIBuilder = null;
            myUIBuilder = createUIBuilder(true);

            Vector inspectorPropertiesVector = new Vector();

            // Create page 1
            String pageName1 = "Pattern properties";
            if (myUIBuilder.addInspectorPage(pageName1, PatternUIBuilder.UIPresentation.Table) == null) {
                throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
            }
            // Add SELECTED_CLASS_ROLE property
            if (getStringPropertyValue(SELECTED_CLASS_ROLE) != null) {
                if (myUIBuilder.addPropertyToPage(pageName1, SELECTED_CLASS_ROLE, SELECTED_CLASS_ROLE,
                    PatternUIBuilder.PropertyType.StringChooser, myClassRoleVector.toArray()) == null) {
                    throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
                }
                inspectorPropertiesVector.addElement(SELECTED_CLASS_ROLE);
            }

            // Add PRODUCT property
            boolean allowInterface = true;
            if (myUIBuilder.addClassPropertyToPage(pageName1, PRODUCT, PRODUCT,
                PatternUIBuilder.PropertyType.SingleValue, allowInterface) == null) {
                throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
            }
            inspectorPropertiesVector.addElement(PRODUCT);

            // Add CONCRETE_PRODUCT property
            allowInterface = true;
            if (myUIBuilder.addClassPropertyToPage(pageName1, CONCRETE_PRODUCT, CONCRETE_PRODUCT,
                PatternUIBuilder.PropertyType.MultiValue, true) == null) {
                throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
            }
            inspectorPropertiesVector.addElement(CONCRETE_PRODUCT);

            // Add CREATOR property
            allowInterface = true;
            if (myUIBuilder.addClassPropertyToPage(pageName1, CREATOR, CREATOR,
                PatternUIBuilder.PropertyType.SingleValue, allowInterface) == null) {
                throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
            }
            inspectorPropertiesVector.addElement(CREATOR);

            // Add CONCRETE_CREATOR property
            allowInterface = false;
            if (myUIBuilder.addClassPropertyToPage(pageName1, CONCRETE_CREATOR, CONCRETE_CREATOR,
                PatternUIBuilder.PropertyType.MultiValue, true) == null) {
                throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
            }
            inspectorPropertiesVector.addElement(CONCRETE_CREATOR);

            // Add FACTORY_METHOD_NAME property
            if (myUIBuilder.addPropertyToPage(pageName1, FACTORY_METHOD_NAME, FACTORY_METHOD_NAME,
                PatternUIBuilder.PropertyType.String) == null) {
                throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
            }
            inspectorPropertiesVector.addElement(FACTORY_METHOD_NAME);

            // Add FACTORY_METHOD_PARAMETERS property
            if (myUIBuilder.addPropertyToPage(pageName1, FACTORY_METHOD_PARAMETERS, FACTORY_METHOD_PARAMETERS,
                PatternUIBuilder.PropertyType.ComboBox, myDefaultParameters) == null) {
                throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
            }
            inspectorPropertiesVector.addElement(FACTORY_METHOD_PARAMETERS);

            // Add EXPORT_DOCUMENTATION property
            if (myUIBuilder.AddExportDocumentationProperty(pageName1) == null) {
                throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
            }
            inspectorPropertiesVector.addElement(EXPORT_DOCUMENTATION);

            // Add "Create pattern links" property
            if (myUIBuilder.AddCreatePatternLinksProperty(pageName1) == null) {
                throw new PatternBaseException(CANNOT_CREATE_PATTERN_UI);
            }
            inspectorPropertiesVector.addElement(CREATE_PATTERN_LINKS);

            myUIBuilder.setCreatedPatternUI();
            myUIBuilder.assignListenedInspectorProperties(inspectorPropertiesVector);
            return true;
        }
        catch (PatternBaseException ex) {
            myUIBuilder = null;
            getIdeInspector().clear();
            return false;
       }
    }

    protected void assignActivityResponse() {
        addPropertyMapListener(PRODUCT, new PropertyMapAdapter() {
            public void propertiesChanged(PropertyMapEvent event) {
                if (myInsideListener) {
                    return;
                }
                myInsideListener = true;
                setFactoryMethodParametersCombobox();
                myInsideListener = false;
            }
        });

        // CONCRETE_PRODUCT changed
        addPropertyMapListener(CONCRETE_PRODUCT, new PropertyMapAdapter() {
            public void propertiesChanged(PropertyMapEvent event) {
                if (myInsideListener) {
                    return;
                }

                myInsideListener = true;

                int numProducts = getNumProperties(CONCRETE_PRODUCT);
                int numCreators = getNumProperties(CONCRETE_CREATOR);
                if (numProducts > numCreators) {
                    // add missed creators
                    String concreteProductName = null;
                    int n = 1;
                    Enumeration products = propertiesEnumeration(CONCRETE_PRODUCT);
                    while (products.hasMoreElements()) {
                        concreteProductName = (String) ((Property)products.nextElement()).getValue();
                        if (n > numCreators) {
                            addPropertyValue(CONCRETE_CREATOR, concreteProductName + CREATOR);
                        }
                        n++;
                    }
                    setFactoryMethodParametersCombobox();
                }

                myInsideListener = false;
            }
        });

        addPropertyMapListener(CONCRETE_CREATOR, new PropertyMapAdapter() {
            public void propertiesChanged(PropertyMapEvent event) {
                if (myInsideListener) {
                    return;
                }

                myInsideListener = true;
                myInsideListener = false;
            }
        });

        addPropertyMapListener(SELECTED_CLASS_ROLE, new PropertyMapListener() {
            // SELECTED_CLASS_ROLE changed
            public void propertiesChanged(PropertyMapEvent event) {
                String role = getStringPropertyValue(SELECTED_CLASS_ROLE);
                // Patch [Valentin] 22.05.2000 SCR #18879
                if (role == null) return;
                // End Patch
                SciClass creatorClass = null;
                SciClass productClass = null;
                if (role.equals(PRODUCT)) {
                    productClass = getSelectedClass();
                    creatorClass = SciPatternUtil.findPatternLinkSupplier(productClass, PATTERN_NAME, CREATOR);
                }
                else if (role.equals(CREATOR)) {
                    creatorClass = getSelectedClass();
                    productClass = SciPatternUtil.findPatternLinkSupplier(creatorClass, PATTERN_NAME, PRODUCT);
                }
                else if (role.equals(CONCRETE_PRODUCT)) {
                    productClass = SciPatternUtil.findExtendedPatternLinkClient(getSelectedClass(), PATTERN_NAME, CONCRETE_PRODUCT);
                    if (productClass == null) {
                        setPropertyValue(CONCRETE_PRODUCT, null);
                        addPropertyValue(CONCRETE_PRODUCT, getSelectedClass().getQualifiedName());
                    }
                    else {
                        creatorClass = SciPatternUtil.findPatternLinkSupplier(productClass, PATTERN_NAME, CREATOR);
                    }
                }
                else if (role.equals(CONCRETE_CREATOR)) {
                    creatorClass = SciPatternUtil.findExtendedPatternLinkClient(getSelectedClass(), PATTERN_NAME, CONCRETE_CREATOR);
                    if (creatorClass == null) {
                        setPropertyValue(CONCRETE_CREATOR, null);
                        addPropertyValue(CONCRETE_CREATOR, getSelectedClass().getQualifiedName());
                    }
                    else {
                        productClass = SciPatternUtil.findPatternLinkSupplier(creatorClass, PATTERN_NAME, PRODUCT);
                    }
                }

                if (creatorClass != null) {
                    setPropertyValue(CREATOR, creatorClass.getQualifiedName());
                }
                if (productClass != null) {
                    setPropertyValue(PRODUCT, productClass.getQualifiedName());
                }
                if (productClass != null && creatorClass != null) {
                    SciOperationEnumeration operations = creatorClass.operations();
                    while (operations.hasMoreElements()) {
                        SciOperation operation = operations.nextSciOperation();
                        if (productClass.equals(operation.getReturnType().getReferencedElement())) {
                            setPropertyValue(FACTORY_METHOD_NAME, operation.getName());
                            break;
                        }
                    }
                }

                Vector products = new Vector();
                Vector creators = new Vector();
                Enumeration productEnumeration = SciPatternUtil.findPatternLinkSuppliers(productClass, PATTERN_NAME, CONCRETE_PRODUCT);
                while (productEnumeration.hasMoreElements()) {
                    SciClass product = (SciClass)productEnumeration.nextElement();
                    SciClass creator = SciPatternUtil.findPatternLinkSupplier(product, PATTERN_NAME, CREATOR);
                    products.addElement(product);
                    creators.addElement(creator);
                }

                Enumeration creatorEnumeration = SciPatternUtil.findPatternLinkSuppliers(creatorClass, PATTERN_NAME, CONCRETE_CREATOR);
                while (creatorEnumeration.hasMoreElements()) {
                    SciClass creator = (SciClass)creatorEnumeration.nextElement();
                    if (!creators.contains(creator)) {
                        SciClass product = SciPatternUtil.findPatternLinkSupplier(creator, PATTERN_NAME, PRODUCT);
                        products.addElement(product);
                        creators.addElement(creator);
                    }
                }

                myInsideListener = true;
                for (int i = 0; i < creators.size(); i++) {
                    SciClass product = (SciClass)products.elementAt(i);
                    addPropertyValue(CONCRETE_PRODUCT, (product == null) ? EMPTY_STRING : product.getQualifiedName());

                    SciClass creator = (SciClass)creators.elementAt(i);
                    addPropertyValue(CONCRETE_CREATOR, (creator == null) ? EMPTY_STRING : creator.getQualifiedName());
                }
                myInsideListener = false;
            }
        });
    }

    private PatternUIBuilder    myUIBuilder = null;
    private Vector              myClassRoleVector = new Vector();

    private boolean myInsideListener = false;
    private String[] myDefaultParameters = new String[] { DEFAULT_PARAMETER_SET };

    private static final String CREATOR                     = "Creator";
    private static final String PRODUCT                     = "Product";
    private static final String CONCRETE_CREATOR            = "Concrete creators";
    private static final String CONCRETE_PRODUCT            = "Concrete products";
    private static final String FACTORY_METHOD_NAME         = "Factory method name";
    private static final String FACTORY_METHOD              = "factoryMethod";
    private static final String FACTORY_METHOD_PARAMETERS   = "Factory method parameters";
    private static final String DEFAULT_PARAMETER_SET       = EMPTY_STRING;

    // Message text templates
    private static final String PATTERN_RETURN_NEW          = "\nreturn new {0}({1});\n";
    private static final String PATTERN_CREATOR_NOT_DEFINED = "Concrete creator for each concrete product should be defined.";
    private static final String PATTERN_PRODUCT_NOT_DEFINED = "Concrete product for each concrete creator should be defined.";
}

/*
boolean concreteCreatorExists = concreteCreatorName != null && concreteCreatorName.length() > 0;
boolean concreteProductExists = concreteProductName != null && concreteProductName.length() > 0;
if (!concreteCreatorExists && concreteProductExists) {
    Object[] arguments = { concreteProductName };
    String message = createTextByPattern(PATTERN_CREATOR_NOT_DEFINED, arguments);
    throw new PatternBaseException(message);
}
if (concreteCreatorExists && !concreteProductExists) {
    Object[] arguments = { concreteCreatorName };
    String message = createTextByPattern(PATTERN_PRODUCT_NOT_DEFINED, arguments);
    throw new PatternBaseException(message);
}
if (!concreteCreatorExists) {
    continue;
}
*/
