/*
 * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
 *
 * The contents of this file are subject to the CCM Public
 * License (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.redhat.com/licenses/ccmpl.html.
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language
 * governing rights and limitations under the License.
 *
 */
package com.arsdigita.formbuilder;


import com.arsdigita.formbuilder.util.GlobalizationUtil ; 


// Implemented by the SimpleQuestionnaire
import com.arsdigita.formbuilder.PersistentComponentFactory;

// Every PersistentComponentFactory can create a Bebop Component
import com.arsdigita.bebop.Component;

import com.arsdigita.bebop.FormSection;
import com.arsdigita.bebop.Link;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.ColumnPanel;

import com.arsdigita.bebop.BlockStylable;

import com.arsdigita.formbuilder.ui.FormBuildingPage;

// The questionnaire uses a PersistentForm internally
import com.arsdigita.formbuilder.PersistentForm;

// Used to represent components added to the form

// To represent widgets
import com.arsdigita.formbuilder.PersistentWidget;

// To create labels
import com.arsdigita.formbuilder.PersistentLabel;

// Used to store the questions
import java.util.ArrayList;
import java.util.Collection;

// When iterating of the components of the form
import java.util.Iterator;
import java.util.Collection;

// The questionnaire can be represented as a Bebop form
import com.arsdigita.bebop.Form;

// Every SimpleQuestionnaire has a submit button at the bottom
import com.arsdigita.formbuilder.PersistentSubmit;

// Does some range checking for this class
import com.arsdigita.formbuilder.util.FormBuilderUtil;

// Thrown if the underlying DataObject with given id cannot be found
import com.arsdigita.domain.DataObjectNotFoundException;




// Persisted forms have ids
import java.math.BigDecimal;

// ACS 5 uses Log4J for logging
import org.apache.log4j.Logger;


/**
 * A simple questionnaire is a list of questions and
 * a submit button. Every question is a label-widget pair (a Bebop Label and
 * a Bebop Widget). The SimpleQuestionnaire is a special case of
 * the PersistentForm and uses such an object internally. The
 * questionnaire offers methods to move questions around and
 * remove questions. I chose not to extend the PersistentForm class
 * since the SimpleQuestionnaire is not an extension of that domain
 * object but rather replaces many of its methods (i.e. add(Component))
 * with its own special methods (i.e. addQuestion).
 *
 *
 *
 * @author Peter Marklund
 * @version $Id: //core-platform/dev/src/com/arsdigita/formbuilder/SimpleQuestionnaire.java#11 $
 */
public class SimpleQuestionnaire
    implements PersistentComponentFactory, AttributeMetaDataProvider {

    public static final String versionId = "$Id: //core-platform/dev/src/com/arsdigita/formbuilder/SimpleQuestionnaire.java#11 $ by $Author: dennis $, $DateTime: 2004/04/07 16:07:11 $";

    private static final Logger s_log =
        Logger.getLogger(SimpleQuestionnaire.class.getName());

    // Responsible for persisting and creating the form
    private PersistentForm m_formFactory;

    // Indicates if admin links should be added
    private boolean m_isAdminEnabled = false;

    // The list of questions
    private ArrayList m_questionList = new ArrayList();

    // The default name of the submit button
    private static String s_submitNameDefault = "submit";

    // The Submit button factory. We need this object to be able
    // to set its label
    private PersistentSubmit m_submitFactory;

    private boolean m_submitFactoryChanged = false;

    // A question is a label/widget pair
    private class Question {

        private PersistentLabel m_labelFactory;
        private PersistentWidget m_widgetFactory;

        public Question(PersistentLabel labelFactory,
                        PersistentWidget widgetFactory) {

            m_labelFactory = labelFactory;
            m_widgetFactory = widgetFactory;
        }

        public PersistentLabel getLabelFactory() {
            return m_labelFactory;
        }

        public PersistentWidget getWidgetFactory() {
            return m_widgetFactory;
        }
    }

    // *** Constructors -------------

    /**
     * Default Constructor. Should normally not be used be application
     * developers. Is only here to enable instantiation by FormSectionGenerator
     */
    public SimpleQuestionnaire() {

        m_formFactory = new PersistentForm();

        m_formFactory.setDomainClass(this.getClass().getName());
    }

    /**
     * Construct a new Questionnaire that can be persisted with the
     * save() method.
     */
    public SimpleQuestionnaire(String htmlName, String adminName) {

        m_formFactory = PersistentForm.create(htmlName);

        m_formFactory.setAdminName(adminName);
    }

    public SimpleQuestionnaire(BigDecimal formID)
        throws DataObjectNotFoundException {


        m_formFactory = new PersistentForm(formID);

        initializeComponentsFromDatabase();
    }

    public void save() {

        m_formFactory.save();

        // Add a Submit button. All simple quesionnaires have a submit button
        // at the bottom
        createAndAddSubmitButton();

        if (m_submitFactoryChanged) {
            m_submitFactory.save();
        }

        m_submitFactoryChanged = false;
    }

    /**
     * Indicates if this questionnaire has been saved or not
     */
    public boolean isNew() {

        return m_formFactory.isNew();
    }

    /**
     * Delete this questionnaire. This method will not only delete
     * the Form but also all its contained components.
     *
     */
    public void delete() {

        // We need to fetch the components so that we can delete them too
        // For now we do not support reusable components in the admin UI
        Iterator componentIter = m_formFactory.getComponents().iterator();

        m_formFactory.delete();

        // Delete all components contained in the form
        while (componentIter.hasNext()) {

            PersistentComponentFactory componentFactory =
                (PersistentComponentFactory)componentIter.next();

            componentFactory.delete();
        }
    }

    /**
     * Returns the Bebop Form representing this questionnaire.
     */
    public Component createComponent() {

        // If the factory changed we need to save it first since the form
        // will retrieve info from the database
        if (m_submitFactoryChanged) {
            m_submitFactory.save();

            m_submitFactoryChanged = false;
        }

        Form form = (Form)m_formFactory.createComponent();

        return form;
    }


    /**
     * Add a question after the questions already added.
     *
     * @pre position >= 1
     * @pre position <= m_questionList.size() + 1
     */
    public void addQuestion(String questionText, PersistentWidget widgetFactory) {

        addQuestion(questionText, widgetFactory, getNumberOfQuestions() + 1);
    }

    /**
     * Add a question at the given position.
     * Position refers to the order number of the questions and
     * starts with 1.
     *
     * @pre position >= 1
     * @pre position <= m_questionList.size() + 1
     */
    public void addQuestion(String questionText, PersistentWidget widgetFactory, int position) {

        // Make sure the position is valid
        assertPositionInAddRange(position);

        // Create a new label to add
        PersistentLabel labelFactory = PersistentLabel.create(questionText);
        labelFactory.save();

        addQuestion(labelFactory, widgetFactory, position);
    }

    /**
     * Remove a question at a certain position.
     * Position refers to the order number of the questions and
     * starts with 1.
     *
     * @pre position >= 1
     * @pre position <= m_questionList.size()
     */
    public void removeQuestion(int position) {

        // Remove the question and delete the components
        removeQuestion(position, true);
    }

    /**
     * Move a question from its current position to
     * a new position. Position refers to the order number of the questions and
     * starts with 1.
     *
     * @pre atPostion >= 1
     * @pre atPosition <= m_questionList.size()
     * @pre toPosition >= 1
     * @pre toPosition <= m_questionList.size()
     */
    public void moveQuestion(int atPosition, int toPosition) {

        // Make sure the positions are valid
        assertPositionInCurrentRange(atPosition);
        assertPositionInCurrentRange(toPosition);

        // Store the factories
        Question question = (Question)m_questionList.get(atPosition - 1);
        PersistentLabel labelFactory =
            (PersistentLabel)question.getLabelFactory();
        PersistentWidget widgetFactory =
            (PersistentWidget)question.getWidgetFactory();

        // Remove the question
        removeQuestion(atPosition, false);

        // Insert the question
        addQuestion(labelFactory, widgetFactory, toPosition);
    }

    public PersistentLabel getQuestionLabel(int questionPosition) {

        // Make sure the position is valid
        assertPositionInCurrentRange(questionPosition);

        return ((Question)m_questionList.get(questionPosition - 1)).getLabelFactory();
    }

    public PersistentWidget getQuestionWidget(int questionPosition) {

        // Make sure the position is valid
        assertPositionInCurrentRange(questionPosition);

        return ((Question)m_questionList.get(questionPosition - 1)).getWidgetFactory();
    }

    // *** Internal helper methods

    private void removeQuestion(int position, boolean deleteComponents) {

        // Make sure the position is valid
        assertPositionInCurrentRange(position);

        // Get the label and widget ids and remove those from the domain object
        Question question = (Question)m_questionList.get(position - 1);
        PersistentLabel labelFactory =
            (PersistentLabel)question.getLabelFactory();
        PersistentWidget widgetFactory =
            (PersistentWidget)question.getWidgetFactory();

        m_formFactory.removeComponent(labelFactory);
        m_formFactory.removeComponent(widgetFactory);

        // Remove the question from the list
        m_questionList.remove(position - 1);

        if (deleteComponents) {

            // Delete the components
            labelFactory.delete();
            widgetFactory.delete();
        }
    }

    /**
     * Called only once when a new questionnaire is created
     */
    private void createAndAddSubmitButton() {

        if (m_submitFactory == null) {
            // Create the submit button and save it
            m_submitFactory = PersistentSubmit.create(s_submitNameDefault);
            m_submitFactory.save();

            // Add the submit button
            m_formFactory.addComponent(m_submitFactory);
        }
    }

    /**
     * Loop over the components in the form
     * and add them to the questions list and initialize
     * the submit field
     * We are assuming the following component order:
     * label1, widget1, label2, widget2, ... , labelN, widgetN, submit
     */
    private void initializeComponentsFromDatabase() {

        // Loop over the components of the form and add the ids of the labels
        // and the widgets to the questions list
        java.util.Iterator componentIter = m_formFactory.getComponents().iterator();
        while (componentIter.hasNext()) {

            PersistentComponentFactory factory =
                (PersistentComponentFactory)componentIter.next();

            // If this is the submit we are done
            if (factory instanceof PersistentSubmit) {
                m_submitFactory = (PersistentSubmit)factory;

                break;
            }

            PersistentLabel labelFactory = (PersistentLabel)factory;
            PersistentWidget widgetFactory = (PersistentWidget)componentIter.next();

            m_questionList.add(new Question(labelFactory, widgetFactory));
        }
    }

    private void addQuestion(PersistentLabel labelFactory,
                             PersistentWidget widgetFactory,
                             int position) {

        // Add the label to the domain object
        m_formFactory.addComponent(labelFactory, position * 2 - 1);

        // Add the widget to the domain object
        m_formFactory.addComponent(widgetFactory, position * 2);

        // Update the questions list
        m_questionList.add(position - 1, new Question(labelFactory, widgetFactory));
    }

    private void assertPositionInAddRange(int position) {

        assertPositionInRange(position, getNumberOfQuestions() + 1);
    }

    private void assertPositionInCurrentRange(int position) {

        assertPositionInRange(position, getNumberOfQuestions());
    }

    private void assertPositionInRange(int position, int upperLimit) {

        try {
            FormBuilderUtil.assertArgumentInRange(position, 1, upperLimit);

        } catch (Exception e) {

            throw new IllegalArgumentException("position " + Integer.toString(position) +
                                               "provided to " + this.toString() + " is invalid" +
                                               ", should be between 1 and " +
                                               Integer.toString(upperLimit));
        }
    }

    private void removeComponentObserver() {

        m_formFactory.setComponentAddObserver(null);
    }

    private void addComponentObserver() {

        m_formFactory.setComponentAddObserver(
                                              new ComponentAddObserver() {

                                                  private int m_questionPosition;
                                                  private BigDecimal m_componentID;

                                                  public void beforeAddingComponent(FormSection formSection,
                                                                                    PersistentComponentFactory componentFactory,
                                                                                    int componentPosition) {

                                                      setQuestionPosition(componentPosition);

                                                      // Add a link for adding a component if this is the question label (odd number)
                                                      // and if the process listener does not dictate the parameters to use
                                                      if ( (isLabel(componentPosition) || isSubmit(componentPosition))
                                                           && !SimpleQuestionnaire.this.listenerDictatesParameterSet()) {
                                                          formSection.add(getQuestionAddLink(componentPosition), BlockStylable.FULL_WIDTH);
                                                      }

                                                      // If there are no questions so far add the parameter links
                                                      if (getNumberOfQuestions() == 0
                                                          && SimpleQuestionnaire.this.listenerHasMetaData()) {

                                                          addParameterLinks(formSection);
                                                      }

                                                  }


                                                  public void addingComponent(PersistentComponentFactory componentFactory,
                                                                              int componentPosition,
                                                                              Component component) {

                                                      if (isLabel(componentPosition)) {

                                                          if (isRequired(componentPosition)) {
                                                              // Indicate with the label if answer is required
                                                              Label label = (Label)component;

                                                              label.setLabel(label.getGlobalizedMessage().getKey() + " (required)");
                                                          }
                                                      }
                                                  }

                                                  public void afterAddingComponent(FormSection formSection,
                                                                                   PersistentComponentFactory componentFactory,
                                                                                   int componentPosition) {

                                                      setQuestionPosition(componentPosition);
                                                      m_componentID = componentFactory.getID();

                                                      // If this is a widget - add the edit panel to the right of it
                                                      if (isWidget(componentPosition)) {
                                                          formSection.add(getEditPanel());

                                                          // If this is the last widget - add any parameters below it that the
                                                          // process listener needs
                                                          if (isLastWidget(componentPosition)) {
                                                              addParameterLinks(formSection);
                                                          }
                                                      }
                                                  }

                                                  private boolean isSubmitComponent(int componentPosition) {
                                                      return (SimpleQuestionnaire.this.getNumberOfQuestions() * 2 + 1) == componentPosition ? true : false;
                                                  }

                                                  private Link getQuestionAddLink(int componentPosition) {

                                                      Link addLink = createQuestionLink("Add question here");

                                                      addLink.setVar(FormBuildingPage.instance().m_pageMode.getName(), "add");

                                                      return addLink;
                                                  }

                                                  private void addEditPanelVars(Link link) {

                                                      link.setVar(FormBuildingPage.instance().m_widgetID.getName(),
                                                                  m_componentID.toString());
                                                  }

                                                  private boolean isLabel(int componentPosition) {

                                                      if (isSubmit(componentPosition)) {
                                                          return false;
                                                      }

                                                      return componentPosition % 2 != 0;
                                                  }

                                                  private boolean isSubmit(int componentPosition) {

                                                      // The last component is the submit
                                                      return isLastComponent(componentPosition);
                                                  }

                                                  private boolean isWidget(int componentPosition) {

                                                      return componentPosition % 2 == 0;
                                                  }

                                                  private boolean isLastWidget(int componentPosition) {

                                                      return isWidget(componentPosition) &&
                                                          componentPosition == (getNumberOfComponents() - 1);
                                                  }

                                                  private int getNumberOfQuestions() {

                                                      int numberOfQuestions =
                                                          SimpleQuestionnaire.this.getNumberOfQuestions();

                                                      return numberOfQuestions;
                                                  }

                                                  private int getNumberOfComponents() {

                                                      return getNumberOfQuestions() * 2 + 1;
                                                  }

                                                  private boolean isLastComponent(int componentPosition) {

                                                      return componentPosition == (getNumberOfQuestions() * 2 + 1);
                                                  }

                                                  private Link createLink(String label) {

                                                      Link link = new Link(label, FormBuildingPage.instance().getRelativeURL());

                                                      link.setVar(FormBuildingPage.instance().m_formID.getName(),
                                                                  SimpleQuestionnaire.this.getID().toString());

                                                      return link;
                                                  }

                                                  private Link createQuestionLink(String label) {

                                                      Link link = createLink(label);

                                                      link.setVar(FormBuildingPage.instance().m_questionPosition.getName(),
                                                                  Integer.toString(m_questionPosition));

                                                      return link;
                                                  }

                                                  private Link createEditPanelLink(String label, String pageMode) {

                                                      Link link = createQuestionLink(pageMode);
                                                      addEditPanelVars(link);
                                                      link.setVar(FormBuildingPage.instance().m_pageMode.getName(),
                                                                  pageMode);

                                                      return link;
                                                  }

                                                  private Component getEditPanel() {

                                                      ColumnPanel editPanel = new ColumnPanel(3);

                                                      editPanel.add(createEditPanelLink("edit", "edit"));
                                                      editPanel.add(createEditPanelLink("move", "move"));
                                                      editPanel.add(createEditPanelLink("delete", "delete"));

                                                      return editPanel;
                                                  }

                                                  private void addParameterLinks(FormSection formSection) {

                                                      // Loop over all parameters that do not already have widgets
                                                      Iterator parameterIter =
                                                          SimpleQuestionnaire.this.getParametersWithNoQuestion().iterator();
                                                      while (parameterIter.hasNext()) {

                                                          AttributeMetaData parameterMetaData =
                                                              (AttributeMetaData)parameterIter.next();

                                                          addOneParameterLink(formSection, parameterMetaData.getParameterName());
                                                      }
                                                  }

                                                  private void addOneParameterLink(FormSection formSection, String parameterName) {

                                                      Link parameterLink = createLink("Add question for parameter " + parameterName);

                                                      // Set the page mode to parameter
                                                      parameterLink.setVar(FormBuildingPage.instance().m_pageMode.getName(),
                                                                           "parameter");

                                                      // Set the name of the parameter that we are adding the question for
                                                      parameterLink.setVar(FormBuildingPage.instance().m_parameterName.getName(),
                                                                           parameterName);

                                                      formSection.add(parameterLink);

                                                      // Let the two leftmost columns be empty
                                                      formSection.add(new Label(""));
                                                      formSection.add(new Label(""));
                                                  }

                                                  private int getQuestionPosition(int componentPosition) {

                                                      if (componentPosition % 2 == 0) {
                                                          // Event component numbers. There are two components per question
                                                          return componentPosition / 2;
                                                      } else {
                                                          // The odd components have the same question position as their
                                                          // even twins
                                                          return (componentPosition + 1) / 2;
                                                      }
                                                  }

                                                  private void setQuestionPosition(int componentPosition) {

                                                      m_questionPosition = getQuestionPosition(componentPosition);
                                                  }

                                                  private boolean isRequired(int componentPosition) {

                                                      Question question =
                                                          (Question)SimpleQuestionnaire.this.m_questionList.
                                                          get(getQuestionPosition(componentPosition) - 1);

                                                      PersistentWidget widget = question.getWidgetFactory();

                                                      return FormBuilderUtil.isRequired(widget);
                                                  }
                                              }
                                              );
    }

    // *** Attributes of a Bebop Form

    public String getHtmlName() {
        return m_formFactory.getHTMLName();
    }

    /**
     * Care has been taken to make this method name JavaBean compiant with the
     * htmlName property
     */
    public void setHtmlName(String htmlName) {
        m_formFactory.setHTMLName(htmlName);
    }

    // *** Attribute methods for attributes that normal Bebop forms don't have

    /**
     * Indicates if links should be added to the questionnaire with which the questions
     * can be managed (added, edited and deleted). Those links are needed in the Form
     * Builder administration pages. Per default those links will not be added.
     */
    public void setAdminEnabled(boolean isAdminEnabled) {

        m_isAdminEnabled = isAdminEnabled;

        if (isAdminEnabled) {
            addComponentObserver();

            m_formFactory.setFormContainer(new ColumnPanel(3));
        } else {
            removeComponentObserver();

            m_formFactory.setFormContainer(new ColumnPanel(2));
        }
    }

    public int getNumberOfQuestions() {

        return m_questionList.size();
    }

    /**
     * Every simple questionnaire will have a submit button at the bottom. This
     * method sets the label of that submit button
     */
    public void setSubmitLabel(String submitLabel) {

        getSubmitFactory().setButtonLabel(submitLabel);

        // Remember that the submit button was modified
        // so that we can save the submit before creating the form
        m_submitFactoryChanged = true;
    }

    private PersistentSubmit getSubmitFactory() {

        if (m_submitFactory == null) {
            createAndAddSubmitButton();
        }

        return m_submitFactory;
    }

    public String getSubmitLabel() {

        // To avoid premature saving in an add form it has been
        // submitted return empty string if the questinnaire is new
        // and no submit label has been set
        if (m_formFactory.isNew() && m_submitFactoryChanged == false) {
            return "";
        } else {
            return getSubmitFactory().getButtonLabel();
        }
    }

    public void setAdminName(String adminName) {
        m_formFactory.setAdminName(adminName);
    }

    public String getAdminName() {
        return m_formFactory.getAdminName();
    }

    public void setDescription(String description) {
        m_formFactory.setDescription(description);
    }

    public String getDescription() {
        return m_formFactory.getDescription();
    }

    public void addProcessListener(PersistentProcessListener processListener) {
        m_formFactory.addProcessListener(processListener);
    }

    /**
     * For convenience I provide the test process listener
     * as default
     */
    public Iterator getProcessListeners() {
        return m_formFactory.getProcessListeners();
    }

    public void setID(BigDecimal id) {
        m_formFactory.setID(id);
    }

    public BigDecimal getID() {
        return m_formFactory.getID();
    }

    //*** Attribute metadata
    public AttributeMetaDataList getAttributeMetaData() {

        AttributeMetaDataList list = new AttributeMetaDataList();

        list.add(new AttributeMetaData("adminName", "Administration name", true));
        list.add(new AttributeMetaData("description", "Description"));
        list.add(new AttributeMetaData("htmlName", "HTML name", true));
        list.add(new AttributeMetaData("submitLabel", "Submit button label"));

        // XXX process listener attribute no longer applies
        /*
          Class stringParameterClass = FormBuilderUtil.loadClass("com.arsdigita.bebop.parameters.StringParameter");
          Class interfaceClass = FormBuilderUtil.loadClass("com.arsdigita.bebop.event.FormProcessListener");
          AttributeType processType = new AttributeType(stringParameterClass);
          processType.addValidationListener(new ClassValidationListener(interfaceClass));
          list.add(new AttributeMetaData("processListener",
          "Process listener",
          true,
          false,
          processType));
        */
        return list;
    }

    /**
     * If this returns true add links for questions will not be allowed, otherwise they will. For now,
     * if the process listener supplies any attribute metadata at all we assume that this is a
     * strict contract parameter set for the persistent form to follow. We might make it configurable to soften
     * this constraint later on.
     */
    public boolean listenerDictatesParameterSet() {
        return listenerHasMetaData();
    }

    /**
     * Returns true if the process listener associated with the quesionnaire implements the
     * AttributeMetaDataProvider interface and has more than zero attribute meta data objects
     * that can be fetched via this interface.
     */
    public boolean listenerHasMetaData() {

        // Get the attribute metadata list from the process listener
        AttributeMetaDataList list = getListenerMetaData();

        return (list != null && list.size() > 0);
    }

    public AttributeMetaDataList getListenerMetaData() {

        // Get the process listener class
        Iterator iter = getProcessListeners();

        AttributeMetaDataList data = new AttributeMetaDataList();
        while (iter.hasNext()) {
            try {
                AttributeMetaDataProvider provider = (AttributeMetaDataProvider)iter.next();
                AttributeMetaDataList d = provider.getAttributeMetaData();

                while (d.hasNext()) {
                    data.add(d.next());
                }
            } catch (Exception e) {
                // nada
            }
        }

        return data;
    }

    /**
     * Return a list of AttributeMetaData objects for those parameters of the process listener that do not
     * already have a question added to this form.
     */
    private Collection getParametersWithNoQuestion() {

        ArrayList parameterList = new ArrayList();

        // Loop through the parameters and check if they have questions
        // - if they don't add them to the return list
        AttributeMetaDataList attributeList = getListenerMetaData();
        while (attributeList.hasNext()) {

            AttributeMetaData attributeMetaData = attributeList.next();
            String attributeName = attributeMetaData.getParameterName();

            // This should never happen but if the parameter name is null
            // we cannot use the parameter
            if (attributeName == null) {
                continue;
            }

            // I am using cached values here for simplicity and speed. If another
            // admin concurrently has edited the questionnaire there will be a problem
            // but we can deal with that improbable case
            Iterator questionIter = m_questionList.iterator();
            boolean parameterHasQuestion = false;
            while (questionIter.hasNext()) {

                Question question = (Question)questionIter.next();
                PersistentWidget widget = question.getWidgetFactory();

                if (widget.getParameterName() == null) {
                    continue;
                }

                if (widget.getParameterName().equals(attributeName)) {
                    parameterHasQuestion = true;
                    break;
                }
            } // end question loop

            if (!parameterHasQuestion) {
                parameterList.add(attributeMetaData);
            }
        } // end parameter loop

        return parameterList;
    }
}
