next() is called on this collection.
+ *
+ */
+ @Override
+ public void addOrder(String order) {
+ m_dataCollection.addOrder(order);
+ }
+
+ /**
+ * Returns a DomainObject for the current position in
+ * the collection.
+ *
+ **/
+ @Override
+ public DomainObject getDomainObject() {
+ return new DecisionTreeOptionTarget(m_dataCollection.getDataObject());
+ }
+
+ /**
+ * Returns a Image for the current position in
+ * the collection.
+ *
+ **/
+ public DecisionTreeOptionTarget getTarget() {
+ return (DecisionTreeOptionTarget) getDomainObject();
+ }
+
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeResources.properties b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeResources.properties
new file mode 100644
index 000000000..f115745b5
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeResources.properties
@@ -0,0 +1,44 @@
+error.parameter_name_characters=This parameter can only contain letters, digits, or "-_"
+form.none=-- none --
+form.please_select=-- please select --
+form_label.cancel_url=Cancel URL
+form_label.description=Description
+form_label.instructions=Instructions
+form_label.label=Label
+form_label.match_value=Value to Match
+form_label.parameter_name=Parameter Name
+form_label.section=Section
+form_label.target_section=Target Section
+form_label.target_url=Target URL
+form_label.title=Title
+form_label.value=Value
+form_validation.target_required=Either a target URL or a target section is required.
+form_validation.duplicate_target=Please enter a target URL or a target section, but not both.
+properties.cancel_url=Cancel URL:
+section_options.add_new_option=Add new option
+section_options.add_option=Add Option
+section_options.delete_option=Delete option
+section_options.description=The options that belong to this decision tree's sections.
+section_options.edit_option=Edit Option
+section_options.move_option_name=Move option
+section_options.move_to_beginning=Move to beginning
+section_options.no_options_yet=No options yet
+section_options.title=Section Options
+section_options.view_all_options=View all options
+option_targets.add_new_target=Add new target
+option_targets.add_target=Add Target
+option_targets.delete_target=Delete target
+option_targets.description=The targets that belong to this decision treeS.
+option_targets.edit_target=Edit Target
+option_targets.no_targets_yet=No targets yet
+option_targets.title=Option Targets
+option_targets.view_all_targets=View all targets
+tree_section.submission_cancelled=Submission cancelled
+tree_sections.add_new_section=Add new section
+tree_sections.add_section=Add Section
+tree_sections.delete_section=Delete section
+tree_sections.description=The sections that belong to this decision tree.
+tree_sections.edit_section=Edit Section
+tree_sections.no_sections_yet=No sections yet
+tree_sections.title=Tree Sections
+tree_sections.view_all_sections=View all sections
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeResources_de.properties b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeResources_de.properties
new file mode 100644
index 000000000..28b01b0bb
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeResources_de.properties
@@ -0,0 +1,44 @@
+error.parameter_name_characters=Dieser Parameter lann nur Buchstaben, Zahlen oder "-_" enthalten.
+form.none=-- keine --
+form.please_select=-- bitte ausw\u00e4hlen --
+form_label.cancel_url=URL Abrechen
+form_label.description=Beschreibung
+form_label.instructions=Anweisungen
+form_label.label=Benennung
+form_label.match_value=Korrespondierender Wert
+form_label.parameter_name=Parameter Name
+form_label.section=Sektion
+form_label.target_section=Zielsektion
+form_label.target_url=Ziel-URL
+form_label.title=Titel
+form_label.value=Wert
+form_validation.target_required=Entweder eine Ziel-URL oder eine Ziel-Sektion isr erforderlich.
+form_validation.duplicate_target=Bitte eine Ziel-URL oder eine Ziel-Sektion angeben, aber nicht beides.
+properties.cancel_url=URL Abbrechen:
+section_options.add_new_option=Eine neue Option hinzuf\u00fcgen
+section_options.add_option=Option hinzuf\u00fcgen
+section_options.delete_option=Option l\u00f6schen
+section_options.description=Optionen, die zu dieser Sektion geh\u00f6ren.
+section_options.edit_option=Option bearbeiten
+section_options.move_option_name=Option verschieben
+section_options.move_to_beginning=An den Anfang verschieben
+section_options.no_options_yet=Bisher keine Optionen eingetragen.
+section_options.title=Optionen in der Sektion
+section_options.view_all_options=Alle Optionen anzeigen
+option_targets.add_new_target=Ein neues Ziel hinzuf\u00fcgen
+option_targets.add_target=Ziel hinzuf\u00fcgen
+option_targets.delete_target=Ziel l\u00f6schen
+option_targets.description=Ziele, die zu dieser Sektion geh\u00f6ren.
+option_targets.edit_target=Ziel bearbeiten
+option_targets.no_targets_yet=Bisher keine Ziele verf\u00fcgbar.
+option_targets.title=Option Targets
+option_targets.view_all_targets=Alle Ziele anzeigen
+tree_section.submission_cancelled=Speichern abgebrochen
+tree_sections.add_new_section=Eine neue Sektion hinzuf\u00fcgen
+tree_sections.add_section=Sektion hinzuf\u00fcgen
+tree_sections.delete_section=Sektion l\u00f6schen
+tree_sections.description=Die Sektionen, die zu diesem Entscheidungsbaum geh\u00f6ren.
+tree_sections.edit_section=Sektion bearbeiten
+tree_sections.no_sections_yet=Bisher keine Sektionen verf\u00fcgbar.
+tree_sections.title=Sektionen
+tree_sections.view_all_sections=Alle Sektionen anzeigen
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeResources_en.properties b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeResources_en.properties
new file mode 100644
index 000000000..f115745b5
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeResources_en.properties
@@ -0,0 +1,44 @@
+error.parameter_name_characters=This parameter can only contain letters, digits, or "-_"
+form.none=-- none --
+form.please_select=-- please select --
+form_label.cancel_url=Cancel URL
+form_label.description=Description
+form_label.instructions=Instructions
+form_label.label=Label
+form_label.match_value=Value to Match
+form_label.parameter_name=Parameter Name
+form_label.section=Section
+form_label.target_section=Target Section
+form_label.target_url=Target URL
+form_label.title=Title
+form_label.value=Value
+form_validation.target_required=Either a target URL or a target section is required.
+form_validation.duplicate_target=Please enter a target URL or a target section, but not both.
+properties.cancel_url=Cancel URL:
+section_options.add_new_option=Add new option
+section_options.add_option=Add Option
+section_options.delete_option=Delete option
+section_options.description=The options that belong to this decision tree's sections.
+section_options.edit_option=Edit Option
+section_options.move_option_name=Move option
+section_options.move_to_beginning=Move to beginning
+section_options.no_options_yet=No options yet
+section_options.title=Section Options
+section_options.view_all_options=View all options
+option_targets.add_new_target=Add new target
+option_targets.add_target=Add Target
+option_targets.delete_target=Delete target
+option_targets.description=The targets that belong to this decision treeS.
+option_targets.edit_target=Edit Target
+option_targets.no_targets_yet=No targets yet
+option_targets.title=Option Targets
+option_targets.view_all_targets=View all targets
+tree_section.submission_cancelled=Submission cancelled
+tree_sections.add_new_section=Add new section
+tree_sections.add_section=Add Section
+tree_sections.delete_section=Delete section
+tree_sections.description=The sections that belong to this decision tree.
+tree_sections.edit_section=Edit Section
+tree_sections.no_sections_yet=No sections yet
+tree_sections.title=Tree Sections
+tree_sections.view_all_sections=View all sections
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeResources_fr.properties b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeResources_fr.properties
new file mode 100644
index 000000000..f115745b5
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeResources_fr.properties
@@ -0,0 +1,44 @@
+error.parameter_name_characters=This parameter can only contain letters, digits, or "-_"
+form.none=-- none --
+form.please_select=-- please select --
+form_label.cancel_url=Cancel URL
+form_label.description=Description
+form_label.instructions=Instructions
+form_label.label=Label
+form_label.match_value=Value to Match
+form_label.parameter_name=Parameter Name
+form_label.section=Section
+form_label.target_section=Target Section
+form_label.target_url=Target URL
+form_label.title=Title
+form_label.value=Value
+form_validation.target_required=Either a target URL or a target section is required.
+form_validation.duplicate_target=Please enter a target URL or a target section, but not both.
+properties.cancel_url=Cancel URL:
+section_options.add_new_option=Add new option
+section_options.add_option=Add Option
+section_options.delete_option=Delete option
+section_options.description=The options that belong to this decision tree's sections.
+section_options.edit_option=Edit Option
+section_options.move_option_name=Move option
+section_options.move_to_beginning=Move to beginning
+section_options.no_options_yet=No options yet
+section_options.title=Section Options
+section_options.view_all_options=View all options
+option_targets.add_new_target=Add new target
+option_targets.add_target=Add Target
+option_targets.delete_target=Delete target
+option_targets.description=The targets that belong to this decision treeS.
+option_targets.edit_target=Edit Target
+option_targets.no_targets_yet=No targets yet
+option_targets.title=Option Targets
+option_targets.view_all_targets=View all targets
+tree_section.submission_cancelled=Submission cancelled
+tree_sections.add_new_section=Add new section
+tree_sections.add_section=Add Section
+tree_sections.delete_section=Delete section
+tree_sections.description=The sections that belong to this decision tree.
+tree_sections.edit_section=Edit Section
+tree_sections.no_sections_yet=No sections yet
+tree_sections.title=Tree Sections
+tree_sections.view_all_sections=View all sections
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeSection.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeSection.java
new file mode 100644
index 000000000..ee5f69400
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeSection.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes;
+
+import java.math.BigDecimal;
+
+import org.apache.log4j.Logger;
+
+import com.arsdigita.cms.ContentPage;
+import com.arsdigita.cms.TextAsset;
+import com.arsdigita.domain.DataObjectNotFoundException;
+import com.arsdigita.persistence.DataCollection;
+import com.arsdigita.persistence.DataObject;
+import com.arsdigita.persistence.OID;
+
+/**
+ * A section of the Camden Decision Tree content type.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeSection extends ContentPage {
+
+ public static final Logger s_log = Logger.getLogger(DecisionTreeSection.class);
+
+ public static final String BASE_DATA_OBJECT_TYPE =
+ "com.arsdigita.cms.contenttypes.DecisionTreeSection";
+
+ public static final String PARAMETER_NAME = "parameterName";
+ public static final String INSTRUCTIONS = "instructions";
+ public static final String SECTION_OPTIONS = "sectionOptions";
+ public static final String TREE = "tree";
+
+ public DecisionTreeSection() {
+ this(BASE_DATA_OBJECT_TYPE);
+ }
+
+ public DecisionTreeSection(OID oid) throws DataObjectNotFoundException {
+ super(oid);
+ }
+
+ public DecisionTreeSection(BigDecimal id) throws DataObjectNotFoundException {
+ this(new OID(BASE_DATA_OBJECT_TYPE, id));
+ }
+
+ public DecisionTreeSection(DataObject obj) {
+ super(obj);
+ }
+
+ public DecisionTreeSection(String type) {
+ super(type);
+ }
+
+ @Override
+ public String getBaseDataObjectType() {
+ return BASE_DATA_OBJECT_TYPE;
+ }
+
+ @Override
+ protected void beforeDelete() {
+ super.beforeDelete();
+
+ // Clear the DecisionTree's firstSection field if it points to
+ // this TreeSection.
+ DecisionTree tree = getTree();
+ if (this.equals(tree.getFirstSection())) {
+ tree.setFirstSection(null);
+ }
+
+ // Delete all OptionTargets which have this TreeSection as their target.
+ DecisionTreeOptionTargetCollection targets = tree.getTargets();
+ targets.addEqualsFilter("targetSection.id", getID());
+ while (targets.next()) {
+ targets.getTarget().delete();
+ }
+ }
+
+ public String getParameterName() {
+ return (String) get(PARAMETER_NAME);
+ }
+
+ public void setParameterName(String value) {
+ set(PARAMETER_NAME, value);
+ }
+
+ public TextAsset getInstructions() {
+ DataObject dataObject = (DataObject)get(INSTRUCTIONS);
+ if (dataObject == null) { return null; }
+ return new TextAsset(dataObject);
+ }
+
+ public void setInstructions(TextAsset value) {
+ setAssociation(INSTRUCTIONS, value);
+ }
+
+ public DecisionTreeSectionOptionCollection getOptions() {
+ return new DecisionTreeSectionOptionCollection(
+ (DataCollection) get(SECTION_OPTIONS));
+ }
+
+ public DecisionTree getTree() {
+ return new DecisionTree((DataObject) get(TREE));
+ }
+
+ public int getMaxOptionRank() {
+ DecisionTreeSectionOptionCollection options = getOptions();
+ options.addOrder(DecisionTreeSectionOption.RANK + " desc");
+
+ int maxRank = 0;
+ if (options.next())
+ maxRank = options.getOption().getRank().intValue();
+ options.close();
+
+ return maxRank;
+ }
+
+ /**
+ * Change the rank of the option with the given id within this object.
+ * Sets the option rank to that given, and moves all other option ranks
+ * as appropriate. If the new rank is greater than the current rank,
+ * options in between will be moved to a numerically lower rank. If the
+ * new rank is less than the current rank than options in between will be
+ * moved to a higher rank.
+ *
+ * @param source the option to reorder
+ * @param rank the new rank for the option. This must be between 1 and
+ * the max section rank inclusively.
+ */
+ public void changeOptionRank(DecisionTreeSectionOption source, int destRank) {
+ Integer r = source.getRank();
+ if (r == null) {
+ throw new IllegalStateException(source + " has null rank");
+ }
+
+ int curRank = r.intValue();
+
+ if (s_log.isDebugEnabled()) {
+ s_log.debug("*** changeSectionRank, section ID = " + source.getID() +
+ ", curRank = " + curRank +
+ ", destRank = " + destRank);
+ }
+
+ DecisionTreeSectionOptionCollection coll = getOptions();
+ coll.addOrder(DecisionTreeSectionOption.RANK);
+ if (curRank > destRank) {
+ coll.setRange(new Integer(destRank), new Integer(curRank));
+ int rank = destRank;
+ while (coll.next()) {
+ DecisionTreeSectionOption cur = coll.getOption();
+ cur.setRank(new Integer(rank + 1));
+ cur.save();
+ rank++;
+ }
+ source.setRank(new Integer(destRank));
+ } else if (curRank < destRank) {
+ coll.setRange(new Integer(curRank + 1), new Integer(destRank + 1));
+ int rank = curRank + 1;
+ while (coll.next()) {
+ DecisionTreeSectionOption cur = coll.getOption();
+ cur.setRank(new Integer(rank - 1));
+ cur.save();
+ rank++;
+ }
+ source.setRank(new Integer(destRank));
+ }
+ coll.close();
+ }
+
+}
\ No newline at end of file
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeSectionCollection.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeSectionCollection.java
new file mode 100644
index 000000000..915002162
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeSectionCollection.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes;
+
+import com.arsdigita.domain.DomainCollection;
+import com.arsdigita.domain.DomainObject;
+import com.arsdigita.persistence.DataCollection;
+
+/**
+ * This class contains a collection of TreeSection objects.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeSectionCollection extends DomainCollection {
+
+ public static final String versionId = "$Id$";
+
+ /**
+ * Constructor.
+ *
+ **/
+ public DecisionTreeSectionCollection(DataCollection dataCollection) {
+ super(dataCollection);
+ }
+
+ /**
+ * Set the order of this Collection. This method needs to be called
+ * before next() is called on this collection.
+ *
+ */
+ @Override
+ public void addOrder(String order) {
+ m_dataCollection.addOrder(order);
+ }
+
+ /**
+ * Returns a DomainObject for the current position in
+ * the collection.
+ *
+ **/
+ public DomainObject getDomainObject() {
+ return new DecisionTreeSection(m_dataCollection.getDataObject());
+ }
+
+ /**
+ * Returns a Image for the current position in
+ * the collection.
+ *
+ **/
+ public DecisionTreeSection getSection() {
+ return (DecisionTreeSection) getDomainObject();
+ }
+
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeSectionOption.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeSectionOption.java
new file mode 100644
index 000000000..c6ac9a5f1
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeSectionOption.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes;
+
+import java.math.BigDecimal;
+
+import org.apache.log4j.Logger;
+
+import com.arsdigita.cms.ContentItem;
+import com.arsdigita.domain.DataObjectNotFoundException;
+import com.arsdigita.persistence.DataObject;
+import com.arsdigita.persistence.OID;
+
+/**
+ * A section option of the Camden Decision Tree content type.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeSectionOption extends ContentItem {
+ private static final Logger s_log = Logger.getLogger(
+ DecisionTreeSectionOption.class);
+
+ public static final String BASE_DATA_OBJECT_TYPE =
+ "com.arsdigita.cms.contenttypes.DecisionTreeSectionOption";
+
+ public static final String TREE_SECTION = "treeSection";
+ public static final String RANK = "rank";
+ public static final String LABEL = "label";
+ public static final String VALUE = "value";
+
+ public DecisionTreeSectionOption() {
+ this(BASE_DATA_OBJECT_TYPE);
+ }
+
+ public DecisionTreeSectionOption(OID oid)
+ throws DataObjectNotFoundException {
+ super(oid);
+ }
+
+ public DecisionTreeSectionOption(BigDecimal id)
+ throws DataObjectNotFoundException {
+ this(new OID(BASE_DATA_OBJECT_TYPE, id));
+ }
+
+ public DecisionTreeSectionOption(DataObject obj) {
+ super(obj);
+ }
+
+ public DecisionTreeSectionOption(String type) {
+ super(type);
+ }
+
+ /**
+ * @return the base PDL object type for this item. Child classes
+ * should override this method to return the correct value.
+ */
+ @Override
+ public String getBaseDataObjectType() {
+ return BASE_DATA_OBJECT_TYPE;
+ }
+
+ public DecisionTreeSection getSection() {
+ DataObject dataObject = (DataObject) get(TREE_SECTION);
+ if (dataObject == null) { return null; }
+ return new DecisionTreeSection(dataObject);
+ }
+
+ public void setSection(DecisionTreeSection value) {
+ setAssociation(TREE_SECTION, value);
+ }
+
+ public Integer getRank() {
+ return (Integer) get(RANK);
+ }
+
+ public void setRank(Integer value) {
+ set(RANK, value);
+ }
+
+ public String getLabel() {
+ return (String) get(LABEL);
+ }
+
+ public void setLabel(String value) {
+ set(LABEL, value);
+ }
+
+ public String getValue() {
+ return (String) get(VALUE);
+ }
+
+ public void setValue(String value) {
+ set(VALUE, value);
+ }
+
+}
\ No newline at end of file
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeSectionOptionCollection.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeSectionOptionCollection.java
new file mode 100644
index 000000000..65bda955e
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeSectionOptionCollection.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes;
+
+import com.arsdigita.domain.DomainCollection;
+import com.arsdigita.domain.DomainObject;
+import com.arsdigita.persistence.DataCollection;
+
+/**
+ * This class contains a collection of SectionOption objects.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeSectionOptionCollection extends DomainCollection {
+
+ /**
+ * Constructor.
+ *
+ **/
+ public DecisionTreeSectionOptionCollection(DataCollection dataCollection) {
+ super(dataCollection);
+ }
+
+ /**
+ * Set the order of this Collection. This method needs to be called
+ * before next() is called on this collection.
+ *
+ */
+ @Override
+ public void addOrder(String order) {
+ m_dataCollection.addOrder(order);
+ }
+
+ /**
+ * Returns a DomainObject for the current position in
+ * the collection.
+ *
+ **/
+ @Override
+ public DomainObject getDomainObject() {
+ return new DecisionTreeSectionOption(m_dataCollection.getDataObject());
+ }
+
+ /**
+ * Returns a Image for the current position in
+ * the collection.
+ *
+ **/
+ public DecisionTreeSectionOption getOption() {
+ return (DecisionTreeSectionOption) getDomainObject();
+ }
+
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeTraversalAdapter.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeTraversalAdapter.java
new file mode 100644
index 000000000..78a1fe031
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeTraversalAdapter.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes;
+
+import java.math.BigDecimal;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.log4j.Logger;
+
+import com.arsdigita.cms.contenttypes.ContentItemTraversalAdapter;
+import com.arsdigita.dispatcher.DispatcherHelper;
+import com.arsdigita.domain.DataObjectNotFoundException;
+import com.arsdigita.domain.DomainObject;
+import com.arsdigita.domain.SimpleDomainObjectTraversalAdapter;
+import com.arsdigita.persistence.metadata.Property;
+
+/**
+ *
+ *
+ */
+public class DecisionTreeTraversalAdapter extends
+ ContentItemTraversalAdapter {
+
+ private static final Logger s_log = Logger.getLogger(DecisionTreeTraversalAdapter.class);
+
+ /**
+ *
+ */
+ public DecisionTreeTraversalAdapter() {}
+
+ /**
+ *
+ * @param adapter
+ */
+ public DecisionTreeTraversalAdapter(SimpleDomainObjectTraversalAdapter adapter) {
+ super(adapter);
+ }
+
+ /**
+ *
+ * @param obj
+ * @param path
+ * @param prop
+ * @param context
+ * @return
+ */
+ @Override
+ public boolean processProperty(DomainObject obj, String path,
+ Property prop, String context) {
+
+ HttpServletRequest request = DispatcherHelper.getRequest();
+
+ if ("/object/sections/title".equals(path) ||
+ "/object/sections/instructions".equals(path) ||
+ "/object/sections/sectionOptions".equals(path)) {
+ // Only include one TreeSection in the output.
+ // Which one depends on the section_id parameter.
+ DecisionTreeSection section = (DecisionTreeSection) obj;
+ DecisionTreeSection selectedSection = null;
+ String sectionID = request.getParameter("section_id");
+ if (sectionID == null || "".equals(sectionID)) {
+ DecisionTree tree = section.getTree();
+ selectedSection = tree.getFirstSection();
+
+ if (selectedSection == null) {
+ throw new RuntimeException("The first section has not been set for tree " + tree);
+ }
+ } else {
+ try {
+ selectedSection = new
+ DecisionTreeSection(new BigDecimal(sectionID));
+ }
+ catch (DataObjectNotFoundException e) {
+ throw new RuntimeException("Cannot find section for section_id parameter " + sectionID);
+ }
+ }
+
+ return section.equals(selectedSection);
+ } else {
+ return super.processProperty(obj, path, prop, context);
+ }
+ }
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeUtil.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeUtil.java
new file mode 100644
index 000000000..75a2a6537
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/DecisionTreeUtil.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes;
+
+import com.arsdigita.globalization.GlobalizedMessage;
+
+
+/**
+ * Miscellaneous utility methods for the Decision Tree content type.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeUtil {
+ public static final String BUNDLE_NAME =
+ "com.arsdigita.camden.cms.contenttypes.DecisionTreeResources";
+
+ public static GlobalizedMessage globalize(String key) {
+ return new GlobalizedMessage(key, BUNDLE_NAME);
+ }
+
+ public static GlobalizedMessage globalize(String key, Object[] args) {
+ return new GlobalizedMessage(key, BUNDLE_NAME, args);
+ }
+
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeOptionDeleteForm.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeOptionDeleteForm.java
new file mode 100644
index 000000000..82a0e2453
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeOptionDeleteForm.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+
+import java.math.BigDecimal;
+
+import org.apache.log4j.Logger;
+
+import com.arsdigita.bebop.ColumnPanel;
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.event.FormInitListener;
+import com.arsdigita.bebop.event.FormProcessListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.event.FormSubmissionListener;
+import com.arsdigita.cms.contenttypes.DecisionTreeSectionOption;
+import com.arsdigita.cms.contenttypes.DecisionTreeUtil;
+import com.arsdigita.cms.ItemSelectionModel;
+
+/**
+ * A form to confirm deletion of a single section of a DecisionTree.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeOptionDeleteForm extends Form
+ implements FormInitListener,
+ FormSubmissionListener,
+ FormProcessListener
+{
+ private final static Logger s_log = Logger.getLogger(
+ DecisionTreeOptionDeleteForm.class.getName());
+
+ protected ItemSelectionModel m_selTree;
+ protected ItemSelectionModel m_selOption;
+ protected SaveCancelSection m_saveCancelSection;
+ private Label m_optionLabel;
+
+ /**
+ *
+ * @param selTree
+ * @param selOption
+ */
+ public DecisionTreeOptionDeleteForm (ItemSelectionModel selTree,
+ ItemSelectionModel selOption) {
+
+ super("DecisionTreeOptionDeleteForm", new ColumnPanel(2));
+ m_selTree = selTree;
+ m_selOption = selOption;
+
+ ColumnPanel panel = (ColumnPanel)getPanel();
+ panel.setBorder(false);
+ panel.setPadColor("#FFFFFF");
+ panel.setColumnWidth(1, "20%");
+ panel.setColumnWidth(2, "80%");
+ panel.setWidth("100%");
+
+ m_optionLabel = new Label("Option Label");
+ add(m_optionLabel, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);
+ addSaveCancelSection();
+
+ addInitListener(this);
+ addSubmissionListener(this);
+ addProcessListener(this);
+ }
+
+ /**
+ *
+ * @return
+ */
+ protected SaveCancelSection addSaveCancelSection () {
+ m_saveCancelSection = new SaveCancelSection();
+ m_saveCancelSection.getSaveButton().setButtonLabel("Delete");
+ add(m_saveCancelSection, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);
+ return m_saveCancelSection;
+ }
+
+ /**
+ *
+ * @param event
+ * @throws FormProcessException
+ */
+ public void init ( FormSectionEvent event ) throws FormProcessException {
+ PageState state = event.getPageState();
+
+ BigDecimal id = new BigDecimal(m_selOption
+ .getSelectedKey(state).toString());
+ DecisionTreeSectionOption option = new DecisionTreeSectionOption(id);
+
+ m_optionLabel.setLabel(option.getLabel(), state);
+ }
+
+ public void submitted ( FormSectionEvent event ) throws FormProcessException {
+ PageState state = event.getPageState();
+
+ if ( m_saveCancelSection.getCancelButton().isSelected(state) ) {
+ throw new FormProcessException( (String) DecisionTreeUtil
+ .globalize("tree_section.submission_cancelled").localize());
+ }
+ }
+
+ public void process ( FormSectionEvent event ) throws FormProcessException {
+ PageState state = event.getPageState();
+
+ BigDecimal id = new BigDecimal(m_selOption
+ .getSelectedKey(state).toString());
+ DecisionTreeSectionOption option = new DecisionTreeSectionOption(id);
+
+ option.delete();
+ }
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeOptionEditForm.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeOptionEditForm.java
new file mode 100644
index 000000000..a8f64828d
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeOptionEditForm.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+import java.math.BigDecimal;
+import java.util.TooManyListenersException;
+
+import org.apache.log4j.Logger;
+
+import com.arsdigita.bebop.ColumnPanel;
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.FormData;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.Page;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.event.FormInitListener;
+import com.arsdigita.bebop.event.FormProcessListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.event.FormSubmissionListener;
+import com.arsdigita.bebop.event.PrintEvent;
+import com.arsdigita.bebop.event.PrintListener;
+import com.arsdigita.bebop.form.Option;
+import com.arsdigita.bebop.form.SingleSelect;
+import com.arsdigita.bebop.form.TextField;
+import com.arsdigita.bebop.parameters.NotNullValidationListener;
+import com.arsdigita.bebop.parameters.TrimmedStringParameter;
+import com.arsdigita.cms.contenttypes.DecisionTree;
+import com.arsdigita.cms.contenttypes.DecisionTreeSection;
+import com.arsdigita.cms.contenttypes.DecisionTreeSectionCollection;
+import com.arsdigita.cms.contenttypes.DecisionTreeSectionOption;
+import com.arsdigita.cms.contenttypes.DecisionTreeUtil;
+import com.arsdigita.cms.ItemSelectionModel;
+
+/**
+ * Form to edit a SectionOption for a DecisionTree.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeOptionEditForm extends Form
+ implements FormInitListener,
+ FormProcessListener,
+ FormSubmissionListener {
+
+ private final static Logger s_log = Logger.getLogger(
+ DecisionTreeOptionEditForm.class);
+
+ private ItemSelectionModel m_selTree;
+ private ItemSelectionModel m_selOption;
+
+ private DecisionTreeViewOptions m_container;
+
+ private SaveCancelSection m_saveCancelSection;
+ private SingleSelect m_sectionWidget;
+
+ public static final String LABEL = "label";
+ public static final String VALUE = "value";
+ public static final String SECTION = "section";
+
+ /**
+ * Constructor.
+ *
+ * @param selTree the current article
+ * @param selOption the current section
+ */
+ public DecisionTreeOptionEditForm(ItemSelectionModel selTree,
+ ItemSelectionModel selOption) {
+ this(selTree, selOption, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param selArticle the current article
+ * @param selOption the current section
+ * @param container container which this form is added to
+ */
+ public DecisionTreeOptionEditForm(ItemSelectionModel selTree,
+ ItemSelectionModel selOption,
+ DecisionTreeViewOptions container) {
+ super("DecisionTreeOptionEditForm", new ColumnPanel(2));
+ m_selTree = selTree;
+ m_selOption = selOption;
+ m_container = container;
+
+ setMethod(Form.POST);
+ setEncType("multipart/form-data");
+
+ ColumnPanel panel = (ColumnPanel)getPanel();
+ panel.setBorder(false);
+ panel.setPadColor("#FFFFFF");
+ panel.setColumnWidth(1, "20%");
+ panel.setColumnWidth(2, "80%");
+ panel.setWidth("100%");
+
+ addWidgets();
+ addSaveCancelSection();
+
+ addInitListener(this);
+ addSubmissionListener(this);
+ addProcessListener(this);
+ }
+
+ /**
+ * Instantiate and add a save/cancel section to the form.
+ *
+ * @return the SaveCancelSection that was added
+ */
+ protected SaveCancelSection addSaveCancelSection() {
+ m_saveCancelSection = new SaveCancelSection();
+ add(m_saveCancelSection, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);
+ return m_saveCancelSection;
+ }
+
+ /**
+ * Returns the save/cancel section from this form.
+ */
+ public SaveCancelSection getSaveCancelSection() {
+ return m_saveCancelSection;
+ }
+
+ /**
+ * Set up the dynamic options for the section select widget.
+ */
+ private void initSectionOptions(PrintEvent e) {
+ PageState state = e.getPageState();
+ SingleSelect target = (SingleSelect) e.getTarget();
+ DecisionTree tree = (DecisionTree)m_selTree.getSelectedObject(state);
+
+ if (tree != null) {
+ DecisionTreeSectionCollection sections = tree.getSections();
+ if (sections != null) {
+ while (sections.next()) {
+ DecisionTreeSection section = sections.getSection();
+ Option option = new Option(section.getID().toString(), section.getTitle());
+ target.addOption(option, state);
+ }
+ sections.close();
+ }
+ }
+ }
+
+ /**
+ * Form initialisation hook.
+ */
+ public void init(FormSectionEvent fse) {
+ PageState state = fse.getPageState();
+ FormData data = fse.getFormData();
+
+ if (m_selOption.getSelectedKey(state) != null) {
+ BigDecimal id = new BigDecimal(m_selOption.getSelectedKey(state).toString());
+ // retrieve the selected Option from the persistence layer
+ DecisionTreeSectionOption sectionOption = new DecisionTreeSectionOption(id);
+
+ data.put(SECTION, sectionOption.getSection().getID());
+ data.put(LABEL, sectionOption.getLabel());
+ data.put(VALUE, sectionOption.getValue());
+ }
+ }
+
+ /**
+ * Add form widgets for a Section.
+ */
+ protected void addWidgets() {
+ Option pleaseSelect = new Option("", (String)DecisionTreeUtil.globalize("form.please_select").localize());
+
+ add(new Label(DecisionTreeUtil
+ .globalize("form_label.section")));
+ m_sectionWidget = new SingleSelect(SECTION);
+ m_sectionWidget.addValidationListener(new NotNullValidationListener());
+ m_sectionWidget.addOption(pleaseSelect);
+
+ try {
+ m_sectionWidget.addPrintListener(new PrintListener() {
+ public void prepare(PrintEvent e) {
+ initSectionOptions(e);
+ }
+ });
+ } catch (TooManyListenersException e) {
+ throw new RuntimeException(e);
+ }
+
+ add(m_sectionWidget);
+
+ add(new Label(DecisionTreeUtil
+ .globalize("form_label.label")));
+ TextField labelWidget = new TextField(new TrimmedStringParameter(LABEL));
+ labelWidget.addValidationListener(new NotNullValidationListener());
+ labelWidget.setSize(60);
+ add(labelWidget);
+
+ add(new Label(DecisionTreeUtil.globalize("form_label.value")));
+ TextField valueWidget = new TextField(new TrimmedStringParameter(VALUE));
+ valueWidget.addValidationListener(new NotNullValidationListener());
+ valueWidget.setSize(60);
+ add(valueWidget);
+ }
+
+ /**
+ * Called on form submission. Check to see if the user clicked the
+ * cancel button. If they did, don't continue with the form.
+ */
+ public void submitted(FormSectionEvent event)
+ throws FormProcessException {
+ PageState state = event.getPageState();
+
+ if ( m_saveCancelSection.getCancelButton()
+ .isSelected(state) && m_container != null) {
+ m_container.onlyShowComponent(
+ state, DecisionTreeViewOptions.OPTION_TABLE +
+ m_container.getTypeIDStr());
+ throw new FormProcessException(
+ (String)DecisionTreeUtil
+ .globalize("tree_section.submission_cancelled")
+ .localize());
+ }
+ }
+
+ /**
+ * Called after form has been validated. Create the new SectionOption and
+ * assign it to the current DecisionTree.
+ */
+ public void process(FormSectionEvent event) throws FormProcessException {
+ PageState state = event.getPageState();
+ FormData data = event.getFormData();
+
+ DecisionTreeSection section = new DecisionTreeSection(new BigDecimal((String)data.get(SECTION)));
+
+ DecisionTreeSectionOption option = null;
+ if (m_selOption.getSelectedKey(state) != null) {
+ BigDecimal id = new BigDecimal(m_selOption
+ .getSelectedKey(state).toString());
+ // retrieve the selected Option from the persistence layer
+ option = new DecisionTreeSectionOption(id);
+ } else {
+ option = new DecisionTreeSectionOption();
+ option.setName("DecisionTreeSectionOption " + option.getID());
+ int rank = section.getMaxOptionRank() + 1;
+ option.setRank(Integer.valueOf(rank));
+ }
+
+ String label = (String)data.get(LABEL);
+ String value = (String)data.get(VALUE);
+
+ option.setSection(section);
+ option.setLabel(label);
+ option.setValue(value);
+
+ if (m_container != null) {
+ m_container.onlyShowComponent(
+ state,
+ DecisionTreeViewOptions.OPTION_TABLE +
+ m_container.getTypeIDStr());
+ }
+ }
+
+ public void register(Page p) {
+ super.register(p);
+ }
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeOptionTable.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeOptionTable.java
new file mode 100644
index 000000000..3af9f9858
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeOptionTable.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+import java.math.BigDecimal;
+
+import org.apache.log4j.Logger;
+
+import com.arsdigita.bebop.Component;
+import com.arsdigita.bebop.ControlLink;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.Table;
+import com.arsdigita.bebop.event.TableActionEvent;
+import com.arsdigita.bebop.event.TableActionListener;
+import com.arsdigita.bebop.table.TableCellRenderer;
+import com.arsdigita.bebop.table.TableColumn;
+import com.arsdigita.bebop.table.TableColumnModel;
+import com.arsdigita.bebop.table.TableModel;
+import com.arsdigita.bebop.table.TableModelBuilder;
+import com.arsdigita.cms.contenttypes.DecisionTree;
+import com.arsdigita.cms.contenttypes.DecisionTreeSection;
+import com.arsdigita.cms.contenttypes.DecisionTreeSectionOption;
+import com.arsdigita.cms.contenttypes.DecisionTreeSectionOptionCollection;
+import com.arsdigita.cms.ContentItem;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.SecurityManager;
+import com.arsdigita.cms.dispatcher.Utilities;
+import com.arsdigita.util.LockableImpl;
+
+/**
+ * A table that displays the options for the currently
+ * selected DecisionTree.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeOptionTable extends Table
+{
+ // column headings
+ public static final String COL_SECTION = "Section";
+ public static final String COL_OPTION = "Option";
+ public static final String COL_EDIT = "Edit";
+ public static final String COL_MOVE = "Move";
+ public static final String COL_DEL = "Delete";
+
+ private ItemSelectionModel m_selTree;
+ private ItemSelectionModel m_selOption;
+ private ItemSelectionModel m_moveOption;
+
+ private static final Logger s_log = Logger.getLogger(
+ DecisionTreeOptionTable.class);
+
+ /**
+ * Constructor.
+ *
+ * @param selTree a selection model that returns the MultiPartArticle
+ * which holds the sections to display.
+ */
+ public DecisionTreeOptionTable(ItemSelectionModel selTree,
+ ItemSelectionModel moveOption) {
+ super();
+ m_selTree = selTree;
+ m_moveOption = moveOption;
+
+ TableColumnModel model = getColumnModel();
+ model.add(new TableColumn(0, COL_SECTION));
+ model.add(new TableColumn(1, COL_OPTION));
+ model.add(new TableColumn(2, COL_EDIT));
+ model.add(new TableColumn(3, COL_MOVE));
+ model.add(new TableColumn(4, COL_DEL));
+
+ model.get(2).setCellRenderer(new SectionTableCellRenderer(true));
+ model.get(3).setCellRenderer(new SectionTableCellRenderer(true));
+ model.get(4).setCellRenderer(new SectionTableCellRenderer(true));
+
+ setModelBuilder(new OptionTableModelBuilder(m_selTree, m_moveOption));
+
+ addTableActionListener ( new TableActionListener () {
+ public void cellSelected ( TableActionEvent event ) {
+ PageState state = event.getPageState();
+
+ TableColumn col = getColumnModel()
+ .get(event.getColumn().intValue());
+ String colName = (String)col.getHeaderValue();
+
+ if ( COL_MOVE.equals(colName) ) {
+ if ( m_moveOption.getSelectedKey(state) == null ) {
+ m_moveOption.setSelectedKey(state, m_selOption.getSelectedKey(state));
+ } else {
+ BigDecimal id = (BigDecimal) m_moveOption.getSelectedKey(state);
+ DecisionTreeSectionOption option = new DecisionTreeSectionOption(id);
+
+ BigDecimal dest = new BigDecimal((String) event.getRowKey());
+ DecisionTreeSectionOption destOption = new DecisionTreeSectionOption(dest);
+
+ DecisionTreeSection section = option.getSection();
+
+ if (section.equals(destOption.getSection())) {
+ // if option is lower in rank than the dest
+ // then move below is default behavior
+ int rank = destOption.getRank().intValue();
+ if (option.getRank().intValue() > rank) {
+ // otherwise, add one to get "move below"
+ rank++;
+ }
+
+ section.changeOptionRank(option, rank);
+ option.save();
+ }
+ m_moveOption.setSelectedKey(state, null);
+ }
+ }
+ }
+
+ public void headSelected ( TableActionEvent event ) {
+ // do nothing
+ }
+ });
+ }
+
+ public void setOptionModel(ItemSelectionModel selOption) {
+ if (selOption == null) {
+ s_log.warn("null item model");
+ }
+ m_selOption = selOption;
+ }
+
+ /**
+ * The model builder to generate a suitable model for the OptionTable
+ */
+ protected class OptionTableModelBuilder extends LockableImpl
+ implements TableModelBuilder
+ {
+ protected ItemSelectionModel m_selTree;
+ protected ItemSelectionModel m_moveOption;
+
+ public OptionTableModelBuilder(ItemSelectionModel selTree, ItemSelectionModel moveOption) {
+ m_selTree = selTree;
+ m_moveOption = moveOption;
+ }
+
+ public TableModel makeModel(Table table, PageState state) {
+ table.getRowSelectionModel().clearSelection(state);
+ DecisionTree tree = (DecisionTree)m_selTree.getSelectedObject(state);
+ return new OptionTableModel(table, state, tree, m_moveOption);
+ }
+ }
+
+ protected class OptionTableModel implements TableModel
+ {
+ private TableColumnModel m_colModel;
+ private PageState m_state;
+ private DecisionTreeSectionOptionCollection m_options;
+ private ItemSelectionModel m_moveOption;
+ private DecisionTreeSectionOption m_option;
+
+ /** Constructor. */
+ public OptionTableModel(Table table, PageState state, DecisionTree tree, ItemSelectionModel moveOption) {
+ m_colModel = table.getColumnModel();
+ m_state = state;
+ m_options = tree.getOptions();
+ m_moveOption = moveOption;
+ }
+
+ /** Return the number of columsn this TableModel has. */
+ public int getColumnCount() {
+ return m_colModel.size();
+ }
+
+ /** Move to the next row and return true if the model is now positioned on
+ * a valid row.
+ */
+ public boolean nextRow() {
+ if (m_options.next()) {
+ m_option = (DecisionTreeSectionOption) m_options.getOption();
+ return true;
+ }
+ return false;
+ }
+
+ /** Return the data element for the given column and the current row. */
+ public Object getElementAt(int columnIndex) {
+ if (m_colModel == null) { return null; }
+
+ // match columns by name... makes for easier reordering
+ TableColumn col = m_colModel.get(columnIndex);
+ String colName = (String) col.getHeaderValue();
+
+ if (COL_SECTION.equals(colName)) {
+ return m_option.getSection().getTitle();
+ } else if (COL_OPTION.equals(colName)) {
+ return m_option.getLabel();
+ } else if (COL_EDIT.equals(colName)) {
+ return "edit";
+ } else if (COL_MOVE.equals(colName)) {
+ if ( m_moveOption.getSelectedKey(m_state) == null ) {
+ return "move";
+ } else {
+ DecisionTreeSectionOption src = new DecisionTreeSectionOption(new BigDecimal((String) m_moveOption.getSelectedKey(m_state)));
+ if (m_option.getSection().equals(src.getSection()))
+ return "move below here";
+ else
+ return "";
+ }
+ } else if (COL_DEL.equals(colName)) {
+ return "delete";
+ }
+
+ return null;
+ }
+
+ /** Return the key for the given column and the current row. */
+ public Object getKeyAt(int columnIndex) {
+ return m_option.getID();
+ }
+ }
+
+ public class SectionTableCellRenderer extends LockableImpl
+ implements TableCellRenderer
+ {
+ private boolean m_active;
+
+ public SectionTableCellRenderer () {
+ this(false);
+ }
+
+ public SectionTableCellRenderer(boolean active) {
+ m_active = active;
+ }
+
+ public Component getComponent(Table table, PageState state,
+ Object value, boolean isSelected,
+ Object key, int row, int column) {
+ Component ret = null;
+ SecurityManager sm = Utilities.getSecurityManager(state);
+ ContentItem item = (ContentItem)m_selTree.getSelectedObject(state);
+
+ boolean active = m_active &&
+ sm.canAccess(state.getRequest(), SecurityManager.EDIT_ITEM,
+ item);
+
+ if (value instanceof Component) {
+ ret = (Component)value;
+ } else {
+ if (value == null) {
+ ret = new Label("", false);
+ } else {
+ if (active) {
+ ret = new ControlLink(value.toString());
+ } else {
+ ret = new Label(value.toString());
+ }
+ }
+ }
+
+ return ret;
+ }
+ }
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeParameterNameValidationListener.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeParameterNameValidationListener.java
new file mode 100644
index 000000000..fae0cece5
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeParameterNameValidationListener.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.event.ParameterEvent;
+import com.arsdigita.bebop.parameters.GlobalizedParameterListener;
+import com.arsdigita.bebop.parameters.ParameterData;
+import com.arsdigita.cms.contenttypes.DecisionTreeUtil;
+import com.arsdigita.globalization.GlobalizedMessage;
+
+/**
+ * Verifies that the
+ * parameter's value contains only letters, digits, "-" and "_".
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ **/
+
+public class DecisionTreeParameterNameValidationListener
+ extends GlobalizedParameterListener {
+
+ public DecisionTreeParameterNameValidationListener() {
+ setError(DecisionTreeUtil.globalize("error.parameter_name_characters"));
+ }
+
+ public DecisionTreeParameterNameValidationListener(GlobalizedMessage error) {
+ setError(error);
+ }
+
+ public void validate (ParameterEvent e) throws FormProcessException {
+ ParameterData data = e.getParameterData();
+ Object obj = data.getValue();
+
+ if (obj == null) {
+ return;
+ }
+
+ String value;
+ try {
+ value = (String) obj;
+ } catch (ClassCastException cce) {
+ throw new FormProcessException (cce.getMessage());
+ }
+
+ for (int i = 0; i < value.length(); i++) {
+ char c = value.charAt(i);
+ if (!isPrintableChar(c)) {
+ data.addError(getError());
+ return;
+ }
+ }
+ }
+
+ private boolean isPrintableChar( char c ) {
+ Character.UnicodeBlock block = Character.UnicodeBlock.of( c );
+ return (!Character.isISOControl(c)) &&
+ block != null &&
+ block != Character.UnicodeBlock.SPECIALS;
+ }
+
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreePropertiesForm.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreePropertiesForm.java
new file mode 100644
index 000000000..d1aaf0666
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreePropertiesForm.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+import com.arsdigita.bebop.FormData;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.event.FormInitListener;
+import com.arsdigita.bebop.event.FormProcessListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.event.FormSubmissionListener;
+import com.arsdigita.bebop.form.TextArea;
+import com.arsdigita.bebop.form.TextField;
+import com.arsdigita.bebop.parameters.StringParameter;
+import com.arsdigita.bebop.parameters.TrimmedStringParameter;
+import com.arsdigita.cms.contenttypes.DecisionTree;
+import com.arsdigita.cms.contenttypes.DecisionTreeUtil;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.ui.authoring.BasicPageForm;
+
+/**
+ * CMS authoring form for the Camden Decision Tree content type.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreePropertiesForm extends BasicPageForm implements
+ FormProcessListener, FormInitListener, FormSubmissionListener {
+
+ private final static String ID = "FORM_PROPERTIES";
+ public final static String DESCRIPTION = "description";
+ public final static String CANCEL_URL = "cancelURL";
+
+ private DecisionTreePropertiesStep m_step;
+
+ /**
+ * Creates a new form to edit the Consultation object specified by the item
+ * selection model passed in.
+ *
+ * @param itemModel
+ * The ItemSelectionModel to use to obtain the Article to work on
+ * @param step
+ * The ArticlePropertiesStep which controls this form.
+ */
+ public DecisionTreePropertiesForm(ItemSelectionModel itemModel,
+ DecisionTreePropertiesStep step) {
+ super(ID, itemModel);
+ m_step = step;
+ addSubmissionListener(this);
+ }
+
+ protected void addWidgets() {
+ super.addWidgets();
+
+ add(new Label(DecisionTreeUtil.globalize("form_label.description")));
+
+ TextArea description = new TextArea(new TrimmedStringParameter(DESCRIPTION));
+ description.setRows(5);
+ description.setCols(30);
+ add(description);
+
+ add(new Label(DecisionTreeUtil.globalize("form_label.cancel_url")));
+ TextField cancelURL = new TextField(new StringParameter(CANCEL_URL));
+ cancelURL.setSize(60);
+ add(cancelURL);
+ }
+
+ /** Cancels streamlined editing. */
+ public void submitted(FormSectionEvent fse) {
+ PageState state = fse.getPageState();
+
+ if (m_step != null &&
+ getSaveCancelSection().getCancelButton().isSelected(state)) {
+ m_step.cancelStreamlinedCreation(state);
+ }
+ }
+
+ /** Form processing hook. Saves Event object. */
+ public void process(FormSectionEvent fse) {
+ PageState state = fse.getPageState();
+ FormData data = fse.getFormData();
+
+ DecisionTree decisionTree = (DecisionTree)processBasicWidgets(fse);
+ decisionTree.setDescription((String)data.get(DESCRIPTION));
+ decisionTree.setCancelURL((String)data.get(CANCEL_URL));
+ decisionTree.save();
+
+ if (m_step != null)
+ m_step.maybeForwardToNextStep(state);
+ }
+
+ /** Form initialisation hook. Fills widgets with data. */
+ public void init(FormSectionEvent fse) {
+ DecisionTree item = (DecisionTree)initBasicWidgets(fse);
+
+ FormData data = fse.getFormData();
+ data.put(DESCRIPTION, item.getDescription());
+ data.put(CANCEL_URL, item.getCancelURL());
+ }
+
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreePropertiesStep.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreePropertiesStep.java
new file mode 100644
index 000000000..dea8868ab
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreePropertiesStep.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+import com.arsdigita.bebop.Component;
+import com.arsdigita.cms.contenttypes.DecisionTreeUtil;
+import com.arsdigita.cms.ContentItem;
+import com.arsdigita.cms.ContentPage;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.ui.authoring.AuthoringKitWizard;
+import com.arsdigita.cms.ui.authoring.BasicPageForm;
+import com.arsdigita.cms.ui.authoring.SimpleEditStep;
+import com.arsdigita.cms.ui.workflow.WorkflowLockedComponentAccess;
+import com.arsdigita.cms.util.GlobalizationUtil;
+import com.arsdigita.toolbox.ui.DomainObjectPropertySheet;
+
+/**
+ * CMS authoring step for the Camden Decision Tree content type.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreePropertiesStep extends SimpleEditStep {
+
+ /** The name of the editing sheet added to this step */
+ public static String EDIT_SHEET_NAME = "SHEET_PROPERTIES";
+ public final static String CANCEL_URL = "cancelURL";
+
+ public DecisionTreePropertiesStep(ItemSelectionModel itemModel,
+ AuthoringKitWizard parent) {
+ super(itemModel, parent);
+
+ setDefaultEditKey(EDIT_SHEET_NAME);
+
+ BasicPageForm editSheet;
+
+ editSheet = new DecisionTreePropertiesForm( itemModel, this );
+ add(EDIT_SHEET_NAME, "Edit", new WorkflowLockedComponentAccess(editSheet, itemModel),
+ editSheet.getSaveCancelSection().getCancelButton() );
+
+ setDisplayComponent(getPropertySheet(itemModel));
+ }
+
+ /**
+ * Returns a component that displays the properties of the
+ * Article specified by the ItemSelectionModel passed in.
+ * @param itemModel The ItemSelectionModel to use
+ * @pre itemModel != null
+ * @return A component to display the state of the basic properties
+ * of the release
+ */
+ public static Component getPropertySheet( ItemSelectionModel itemModel ) {
+ DomainObjectPropertySheet sheet = new DomainObjectPropertySheet(itemModel);
+
+ sheet.add(GlobalizationUtil.globalize("cms.contenttypes.ui.name"), ContentItem.NAME);
+ sheet.add(GlobalizationUtil.globalize("cms.contenttypes.ui.title"), ContentPage.TITLE);
+ sheet.add(GlobalizationUtil.globalize("cms.contenttypes.ui.description"), ContentPage.DESCRIPTION);
+ sheet.add(DecisionTreeUtil.globalize("properties.cancel_url"), CANCEL_URL);
+
+ return sheet;
+ }
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeSectionDeleteForm.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeSectionDeleteForm.java
new file mode 100644
index 000000000..093d57a84
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeSectionDeleteForm.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+
+import org.apache.log4j.Logger;
+
+import com.arsdigita.bebop.ColumnPanel;
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.event.FormInitListener;
+import com.arsdigita.bebop.event.FormProcessListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.event.FormSubmissionListener;
+import com.arsdigita.cms.contenttypes.DecisionTree;
+import com.arsdigita.cms.contenttypes.DecisionTreeUtil;
+import com.arsdigita.cms.contenttypes.DecisionTreeSection;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.util.Assert;
+
+/**
+ * A form to confirm deletion of a single section of a DecisionTree.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeSectionDeleteForm extends Form
+ implements FormInitListener, FormSubmissionListener, FormProcessListener
+{
+ private final static Logger log = Logger.getLogger(
+ DecisionTreeSectionDeleteForm.class.getName());
+
+ protected ItemSelectionModel m_selTree;
+ protected ItemSelectionModel m_selSection;
+ protected SaveCancelSection m_saveCancelSection;
+ private Label m_sectionNameLabel;
+
+
+ /**
+ *
+ * @param selArticle
+ * @param selSection
+ */
+ public DecisionTreeSectionDeleteForm( ItemSelectionModel selArticle,
+ ItemSelectionModel selSection) {
+ super("DecisionTreeSectionDeleteForm", new ColumnPanel(2));
+ m_selTree = selArticle;
+ m_selSection = selSection;
+
+ ColumnPanel panel = (ColumnPanel)getPanel();
+ panel.setBorder(false);
+ panel.setPadColor("#FFFFFF");
+ panel.setColumnWidth(1, "20%");
+ panel.setColumnWidth(2, "80%");
+ panel.setWidth("100%");
+
+ m_sectionNameLabel = new Label ("Section Name");
+ add(m_sectionNameLabel, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);
+ addSaveCancelSection();
+
+ addInitListener(this);
+ addSubmissionListener(this);
+ addProcessListener(this);
+ }
+
+ protected SaveCancelSection addSaveCancelSection () {
+ m_saveCancelSection = new SaveCancelSection();
+ m_saveCancelSection.getSaveButton().setButtonLabel("Delete");
+ add(m_saveCancelSection, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);
+ return m_saveCancelSection;
+ }
+
+ public void init ( FormSectionEvent event ) throws FormProcessException {
+ PageState state = event.getPageState();
+
+ DecisionTreeSection section =
+ (DecisionTreeSection)m_selSection.getSelectedObject(state);
+
+ if ( section == null ) {
+ log.error("No section selected");
+ } else {
+ m_sectionNameLabel.setLabel(section.getTitle(),state);
+ }
+ }
+
+ public void submitted ( FormSectionEvent event ) throws FormProcessException {
+ PageState state = event.getPageState();
+
+ if ( m_saveCancelSection.getCancelButton().isSelected(state) ) {
+ throw new FormProcessException( (String) DecisionTreeUtil.globalize("tree_section.submission_cancelled").localize());
+ }
+ }
+
+ public void process ( FormSectionEvent event ) throws FormProcessException {
+ PageState state = event.getPageState();
+
+ DecisionTree article = (DecisionTree)m_selTree.getSelectedObject(state);
+ DecisionTreeSection section = (DecisionTreeSection)m_selSection.getSelectedObject(state);
+
+ Assert.exists(article, DecisionTree.class);
+ Assert.exists(section, DecisionTreeSection.class);
+
+ article.removeSection(section);
+
+ log.info("section " + m_selSection.getSelectedKey(state) + " delete");
+ }
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeSectionEditForm.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeSectionEditForm.java
new file mode 100644
index 000000000..bd862f073
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeSectionEditForm.java
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+
+import java.math.BigDecimal;
+
+import org.apache.log4j.Logger;
+
+import com.arsdigita.bebop.ColumnPanel;
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.FormData;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.Page;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.event.FormInitListener;
+import com.arsdigita.bebop.event.FormProcessListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.event.FormSubmissionListener;
+import com.arsdigita.bebop.form.TextField;
+import com.arsdigita.bebop.parameters.BigDecimalParameter;
+import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
+import com.arsdigita.bebop.parameters.StringIsLettersOrDigitsValidationListener;
+import com.arsdigita.bebop.parameters.TrimmedStringParameter;
+import com.arsdigita.cms.contenttypes.DecisionTree;
+import com.arsdigita.cms.contenttypes.DecisionTreeSection;
+import com.arsdigita.cms.contenttypes.DecisionTreeUtil;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.TextAsset;
+import com.arsdigita.cms.ui.CMSDHTMLEditor;
+import com.arsdigita.domain.DataObjectNotFoundException;
+import com.arsdigita.util.UncheckedWrapperException;
+
+
+/**
+ * Form to edit a TreeSection for a DecisionTree.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeSectionEditForm extends Form
+ implements FormInitListener,
+ FormProcessListener,
+ FormSubmissionListener {
+
+ private final static Logger log = Logger.getLogger(
+ DecisionTreeSectionEditForm.class);
+
+ private ItemSelectionModel m_selTree;
+ private ItemSelectionModel m_selSection;
+
+ private BigDecimalParameter m_instructionsParam;
+ private ItemSelectionModel m_selInstructions;
+ private DecisionTreeViewSections m_container;
+
+ private SaveCancelSection m_saveCancelSection;
+
+ public static final String TITLE = "title";
+ public static final String PARAMETER_NAME = "parameterName";
+ public static final String INSTRUCTIONS = "instructions";
+
+ private static final String INSTRUCTIONS_PARAM = "instructionsParam";
+
+ /**
+ * Constructor.
+ *
+ * @param selTree the current article
+ * @param selSection the current section
+ */
+ public DecisionTreeSectionEditForm(ItemSelectionModel selTree,
+ ItemSelectionModel selSection) {
+ this(selTree, selSection, null);
+ }
+ /**
+ * Constructor.
+ *
+ * @param selArticle the current article
+ * @param selSection the current section
+ * @param container container which this form is added to
+ */
+ public DecisionTreeSectionEditForm(ItemSelectionModel selTree,
+ ItemSelectionModel selSection,
+ DecisionTreeViewSections container) {
+ super("SectionEditForm", new ColumnPanel(2));
+ m_selTree = selTree;
+ m_selSection = selSection;
+ m_container = container;
+
+ m_instructionsParam = new BigDecimalParameter(INSTRUCTIONS_PARAM);
+ m_selInstructions = new ItemSelectionModel(
+ TextAsset.class.getName(),
+ TextAsset.BASE_DATA_OBJECT_TYPE,
+ m_instructionsParam);
+
+ setMethod(Form.POST);
+ setEncType("multipart/form-data");
+
+ ColumnPanel panel = (ColumnPanel)getPanel();
+ panel.setBorder(false);
+ panel.setPadColor("#FFFFFF");
+ panel.setColumnWidth(1, "20%");
+ panel.setColumnWidth(2, "80%");
+ panel.setWidth("100%");
+
+ addWidgets();
+ addSaveCancelSection();
+
+ addInitListener(this);
+ addSubmissionListener(this);
+ addProcessListener(this);
+ }
+
+ /**
+ * Instantiate and add a save/cancel section to the form.
+ *
+ * @return the SaveCancelSection that was added
+ */
+ protected SaveCancelSection addSaveCancelSection() {
+ m_saveCancelSection = new SaveCancelSection();
+ add(m_saveCancelSection, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);
+ return m_saveCancelSection;
+ }
+
+ /**
+ * Returns the save/cancel section from this form.
+ */
+ public SaveCancelSection getSaveCancelSection() {
+ return m_saveCancelSection;
+ }
+
+ /**
+ * Add form widgets for a Section.
+ */
+ protected void addWidgets() {
+ add(new Label(DecisionTreeUtil.globalize("form_label.title")));
+ TextField titleWidget = new TextField(new TrimmedStringParameter(TITLE));
+ titleWidget.addValidationListener(new NotEmptyValidationListener());
+ add(titleWidget);
+
+ add(new Label(DecisionTreeUtil.globalize("form_label.parameter_name")));
+ TextField parameterWidget = new TextField(new TrimmedStringParameter(PARAMETER_NAME));
+ parameterWidget.addValidationListener(new NotEmptyValidationListener());
+ parameterWidget.addValidationListener(new DecisionTreeParameterNameValidationListener());
+ add(parameterWidget);
+
+ add(new Label(DecisionTreeUtil.globalize("form_label.instructions")),
+ ColumnPanel.LEFT | ColumnPanel.FULL_WIDTH);
+ CMSDHTMLEditor textWidget =
+ new CMSDHTMLEditor(new TrimmedStringParameter(INSTRUCTIONS));
+ textWidget.setRows(40);
+ textWidget.setCols(70);
+ textWidget.setWrap(CMSDHTMLEditor.SOFT);
+ add(textWidget,
+ ColumnPanel.LEFT | ColumnPanel.FULL_WIDTH);
+ }
+
+ /**
+ * Initialize the form. If there is a selected section, ie. this
+ * is an 'edit' step rather than a 'create new' step, load the data
+ * into the form fields.
+ */
+ public void init( FormSectionEvent event )
+ throws FormProcessException {
+ PageState state = event.getPageState();
+ FormData data = event.getFormData();
+ m_selInstructions.setSelectedObject(state,null);
+
+ if ( m_selSection.getSelectedKey(state) != null ) {
+ BigDecimal id = new BigDecimal(m_selSection
+ .getSelectedKey(state).toString());
+ try {
+ // retrieve the selected Section from the persistence layer
+ DecisionTreeSection section = new DecisionTreeSection(id);
+
+ data.put(TITLE, section.getTitle());
+ data.put(PARAMETER_NAME, section.getParameterName());
+
+ TextAsset t = section.getInstructions();
+ if ( t != null ) {
+ m_selInstructions.setSelectedObject(state, t);
+ data.put(INSTRUCTIONS, t.getText());
+ }
+
+ } catch ( DataObjectNotFoundException ex ) {
+ log.error("Section(" + id + ") could not be found");
+ }
+ }
+ }
+
+
+ /**
+ * Called on form submission. Check to see if the user clicked the
+ * cancel button. If they did, don't continue with the form.
+ */
+ public void submitted( FormSectionEvent event )
+ throws FormProcessException {
+ PageState state = event.getPageState();
+
+ if ( m_saveCancelSection.getCancelButton()
+ .isSelected(state) && m_container != null) {
+ m_container.onlyShowComponent(
+ state, DecisionTreeViewSections.SECTION_TABLE +
+ m_container.getTypeIDStr());
+ throw new FormProcessException(
+ (String)DecisionTreeUtil
+ .globalize("tree_section.submission_cancelled")
+ .localize());
+ }
+ }
+
+ /**
+ * Called after form has been validated. Create the new TreeSection and
+ * assign it to the current DecisionTree.
+ */
+ public void process(FormSectionEvent event)
+ throws FormProcessException {
+ PageState state = event.getPageState();
+ FormData data = event.getFormData();
+
+ // retrieve the current DecisionTree
+ BigDecimal id = new BigDecimal(
+ m_selTree.getSelectedKey(state).toString());
+
+ DecisionTree tree;
+ try {
+ tree = new DecisionTree(id);
+ } catch ( DataObjectNotFoundException ex ) {
+ throw new UncheckedWrapperException(ex);
+ }
+
+ // get the selected section to update or create a new one
+ DecisionTreeSection section = (DecisionTreeSection)
+ m_selSection.getSelectedObject(state);
+ if (section == null) {
+ section = createSection(event, tree);
+ tree.addSection(section);
+ }
+
+ section.setTitle((String) data.get(TITLE));
+ section.setParameterName((String) data.get(PARAMETER_NAME));
+
+ // get the text asset
+ TextAsset textAsset = (TextAsset)m_selInstructions.getSelectedObject(state);
+ if ( textAsset == null ) {
+ textAsset = new TextAsset();
+ textAsset.setName(section.getName() + " text");
+ m_selInstructions.setSelectedObject(state, textAsset);
+ section.setInstructions(textAsset);
+ }
+
+ String text = (String)data.get(INSTRUCTIONS);
+ if ( text == null ) { text = ""; }
+
+ textAsset.setText(text);
+ if ( m_container != null) {
+ m_container.onlyShowComponent(
+ state,
+ DecisionTreeViewSections.SECTION_TABLE +
+ m_container.getTypeIDStr());
+ }
+ }
+
+ /**
+ * Utility method to create a Section from the form data supplied.
+ */
+ protected DecisionTreeSection createSection(FormSectionEvent event,
+ DecisionTree tree) {
+ FormData data = event.getFormData();
+
+ DecisionTreeSection section = new DecisionTreeSection();
+
+ section.setTitle((String)data.get(TITLE));
+ section.setName(tree.getName() + ": " + (String)data.get(TITLE));
+
+ return section;
+ }
+
+ /**
+ *
+ * @param p
+ */
+ @Override
+ public void register(Page p) {
+ super.register(p);
+ p.addGlobalStateParam(m_instructionsParam);
+ }
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeSectionTable.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeSectionTable.java
new file mode 100644
index 000000000..a4d1c5d6f
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeSectionTable.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+
+import org.apache.log4j.Logger;
+
+import com.arsdigita.bebop.Component;
+import com.arsdigita.bebop.ControlLink;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.Table;
+import com.arsdigita.bebop.table.TableCellRenderer;
+import com.arsdigita.bebop.table.TableColumn;
+import com.arsdigita.bebop.table.TableColumnModel;
+import com.arsdigita.bebop.table.TableModel;
+import com.arsdigita.bebop.table.TableModelBuilder;
+import com.arsdigita.cms.contenttypes.DecisionTree;
+import com.arsdigita.cms.contenttypes.DecisionTreeSection;
+import com.arsdigita.cms.contenttypes.DecisionTreeSectionCollection;
+import com.arsdigita.cms.ContentItem;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.SecurityManager;
+import com.arsdigita.cms.dispatcher.Utilities;
+import com.arsdigita.util.LockableImpl;
+
+
+/**
+ * A table that displays the sections for the currently
+ * selected DecisionTree.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeSectionTable extends Table
+{
+ // column headings
+ public static final String COL_TITLE = "Section";
+ public static final String COL_EDIT = "Edit";
+ public static final String COL_DEL = "Delete";
+ public static final String COL_FIRST = "First Section?";
+
+ private ItemSelectionModel m_selTree;
+
+ private static final Logger s_log = Logger.getLogger(
+ DecisionTreeSectionTable.class);
+
+ /**
+ * Constructor.
+ *
+ * @param selArticle a selection model that returns the MultiPartArticle
+ * which holds the sections to display.
+ */
+ public DecisionTreeSectionTable (ItemSelectionModel selArticle) {
+ super();
+ m_selTree = selArticle;
+
+ TableColumnModel model = getColumnModel();
+ model.add( new TableColumn(0, COL_TITLE));
+ model.add( new TableColumn(1, COL_EDIT));
+ model.add( new TableColumn(2, COL_DEL));
+ model.add( new TableColumn(3, COL_FIRST));
+
+ model.get(1).setCellRenderer(new SectionTableCellRenderer(true));
+ model.get(2).setCellRenderer(new SectionTableCellRenderer(true));
+ model.get(3).setCellRenderer(new SectionTableCellRenderer(true));
+
+ setModelBuilder(new SectionTableModelBuilder(m_selTree));
+ }
+
+ public void setSectionModel ( ItemSelectionModel selSection ) {
+ if ( selSection == null ) {
+ s_log.warn("null item model");
+ }
+ }
+
+ /**
+ * The model builder to generate a suitable model for the SectionTable
+ */
+ protected class SectionTableModelBuilder extends LockableImpl
+ implements TableModelBuilder
+ {
+ protected ItemSelectionModel m_selTree;
+
+ public SectionTableModelBuilder (ItemSelectionModel selTree) {
+ m_selTree = selTree;
+ }
+
+ public TableModel makeModel(Table table, PageState state) {
+ table.getRowSelectionModel().clearSelection(state);
+
+ DecisionTree tree = (DecisionTree)m_selTree.getSelectedObject(state);
+
+ return new SectionTableModel(table, state, tree);
+ }
+ }
+
+ protected class SectionTableModel
+ implements TableModel
+ {
+ private TableColumnModel m_colModel;
+ private DecisionTreeSectionCollection m_sections;
+ private DecisionTreeSection m_section;
+
+ /** Constructor. */
+ public SectionTableModel (Table table, PageState state, DecisionTree tree) {
+ m_colModel = table.getColumnModel();
+ m_sections = tree.getSections();
+ }
+
+ /** Return the number of columsn this TableModel has. */
+ public int getColumnCount () {
+ return m_colModel.size();
+ }
+
+ /** Move to the next row and return true if the model is now positioned on
+ * a valid row.
+ */
+ public boolean nextRow () {
+ if ( m_sections.next() ) {
+ m_section = (DecisionTreeSection)m_sections.getSection();
+ return true;
+ }
+ return false;
+ }
+
+ /** Return the data element for the given column and the current row. */
+ public Object getElementAt(int columnIndex) {
+ if (m_colModel == null) { return null; }
+
+ // match columns by name... makes for easier reordering
+ TableColumn col = m_colModel.get(columnIndex);
+ String colName = (String)col.getHeaderValue();
+
+ if ( COL_TITLE.equals(colName) ) {
+ return m_section.getTitle();
+ } else if ( COL_EDIT.equals(colName) ) {
+ return "edit";
+ } else if ( COL_DEL.equals(colName) ) {
+ return "delete";
+ } else if ( COL_FIRST.equals(colName) ) {
+ DecisionTree tree = m_section.getTree();
+ DecisionTreeSection firstSection = tree.getFirstSection();
+ if (firstSection != null && firstSection.getID() == m_section.getID()) {
+ return "";
+ } else {
+ return "set";
+ }
+ }
+
+ return null;
+ }
+
+ /** Return the key for the given column and the current row. */
+ public Object getKeyAt(int columnIndex) {
+ return m_section.getID();
+ }
+ }
+
+ public class SectionTableCellRenderer extends LockableImpl
+ implements TableCellRenderer
+ {
+ private boolean m_active;
+
+ public SectionTableCellRenderer () {
+ this(false);
+ }
+
+ public SectionTableCellRenderer ( boolean active ) {
+ m_active = active;
+ }
+
+ public Component getComponent ( Table table, PageState state,
+ Object value, boolean isSelected,
+ Object key, int row, int column ) {
+ Component ret = null;
+ SecurityManager sm = Utilities.getSecurityManager(state);
+ ContentItem item = (ContentItem)m_selTree.getSelectedObject(state);
+
+ boolean active = m_active &&
+ sm.canAccess(state.getRequest(), SecurityManager.EDIT_ITEM,
+ item);
+
+ if (value instanceof Component) {
+ ret = (Component)value;
+ } else {
+ if (value == null) {
+ ret = new Label("", false);
+ } else {
+ if (active) {
+ ret = new ControlLink(value.toString());
+ } else {
+ ret = new Label(value.toString());
+ }
+ }
+ }
+
+ return ret;
+ }
+ }
+
+
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeTargetDeleteForm.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeTargetDeleteForm.java
new file mode 100644
index 000000000..0369a0131
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeTargetDeleteForm.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+import java.math.BigDecimal;
+
+import org.apache.log4j.Logger;
+
+import com.arsdigita.bebop.ColumnPanel;
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.event.FormInitListener;
+import com.arsdigita.bebop.event.FormProcessListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.event.FormSubmissionListener;
+import com.arsdigita.cms.contenttypes.DecisionTreeUtil;
+import com.arsdigita.cms.contenttypes.DecisionTreeOptionTarget;
+import com.arsdigita.cms.ItemSelectionModel;
+
+/**
+ * A form to confirm deletion of a single section of a DecisionTree.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeTargetDeleteForm extends Form
+ implements FormInitListener, FormSubmissionListener, FormProcessListener
+{
+ private final static Logger s_log = Logger.getLogger(
+ DecisionTreeTargetDeleteForm.class.getName());
+
+ protected ItemSelectionModel m_selTree;
+ protected ItemSelectionModel m_selTarget;
+ protected SaveCancelSection m_saveCancelSection;
+ private Label m_targetMatchValue;
+
+ /**
+ *
+ * @param selTree
+ * @param selTarget
+ */
+ public DecisionTreeTargetDeleteForm (ItemSelectionModel selTree,
+ ItemSelectionModel selTarget) {
+ super("DecisionTreeTargetDeleteForm", new ColumnPanel(2));
+ m_selTree = selTree;
+ m_selTarget = selTarget;
+
+ ColumnPanel panel = (ColumnPanel)getPanel();
+ panel.setBorder(false);
+ panel.setPadColor("#FFFFFF");
+ panel.setColumnWidth(1, "20%");
+ panel.setColumnWidth(2, "80%");
+ panel.setWidth("100%");
+
+ m_targetMatchValue = new Label("Target Match Value");
+ add(m_targetMatchValue, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);
+ addSaveCancelSection();
+
+ addInitListener(this);
+ addSubmissionListener(this);
+ addProcessListener(this);
+ }
+
+ protected SaveCancelSection addSaveCancelSection () {
+ m_saveCancelSection = new SaveCancelSection();
+ m_saveCancelSection.getSaveButton().setButtonLabel("Delete");
+ add(m_saveCancelSection, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);
+ return m_saveCancelSection;
+ }
+
+ public void init ( FormSectionEvent event ) throws FormProcessException {
+ PageState state = event.getPageState();
+
+ BigDecimal id = new BigDecimal(m_selTarget
+ .getSelectedKey(state).toString());
+ DecisionTreeOptionTarget target = new DecisionTreeOptionTarget(id);
+
+ m_targetMatchValue.setLabel(target.getMatchOption().getLabel(), state);
+ }
+
+ public void submitted ( FormSectionEvent event ) throws FormProcessException {
+ PageState state = event.getPageState();
+
+ if ( m_saveCancelSection.getCancelButton().isSelected(state) ) {
+ throw new FormProcessException( (String)
+ DecisionTreeUtil.globalize("tree_section.submission_cancelled")
+ .localize());
+ }
+ }
+
+ public void process ( FormSectionEvent event ) throws FormProcessException {
+ PageState state = event.getPageState();
+
+ BigDecimal id = new BigDecimal(m_selTarget
+ .getSelectedKey(state).toString());
+ DecisionTreeOptionTarget target = new DecisionTreeOptionTarget(id);
+
+ target.delete();
+ }
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeTargetEditForm.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeTargetEditForm.java
new file mode 100644
index 000000000..b0b263906
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeTargetEditForm.java
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+import java.math.BigDecimal;
+import java.util.TooManyListenersException;
+
+import org.apache.log4j.Logger;
+
+import com.arsdigita.bebop.ColumnPanel;
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.FormData;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.Page;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.event.FormInitListener;
+import com.arsdigita.bebop.event.FormProcessListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.event.FormSubmissionListener;
+import com.arsdigita.bebop.event.FormValidationListener;
+import com.arsdigita.bebop.event.PrintEvent;
+import com.arsdigita.bebop.event.PrintListener;
+import com.arsdigita.bebop.form.Option;
+import com.arsdigita.bebop.form.SingleSelect;
+import com.arsdigita.bebop.form.TextField;
+import com.arsdigita.bebop.parameters.NotNullValidationListener;
+import com.arsdigita.cms.contenttypes.DecisionTree;
+import com.arsdigita.cms.contenttypes.DecisionTreeUtil;
+import com.arsdigita.cms.contenttypes.DecisionTreeSectionOption;
+import com.arsdigita.cms.contenttypes.DecisionTreeSectionOptionCollection;
+import com.arsdigita.cms.contenttypes.DecisionTreeOptionTarget;
+import com.arsdigita.cms.contenttypes.DecisionTreeSection;
+import com.arsdigita.cms.contenttypes.DecisionTreeSectionCollection;
+import com.arsdigita.cms.ItemSelectionModel;
+
+/**
+ * Form to edit an DecisionTreeOptionTarget for a DecisionTree.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeTargetEditForm extends Form
+ implements FormInitListener,
+ FormProcessListener,
+ FormSubmissionListener {
+
+ private final static Logger s_log = Logger.getLogger(
+ DecisionTreeTargetEditForm.class);
+
+ private ItemSelectionModel m_selTree;
+ private ItemSelectionModel m_selTarget;
+
+ private DecisionTreeViewTargets m_container;
+
+ private SaveCancelSection m_saveCancelSection;
+ private SingleSelect m_sectionWidget;
+ private SingleSelect m_matchValueWidget;
+ private SingleSelect m_targetSectionWidget;
+ private TextField m_targetURLWidget;
+
+ public static final String MATCH_OPTION = "matchOption";
+ public static final String TARGET_URL = "targetURL";
+ public static final String TARGET_SECTION = "targetSection";
+
+ /**
+ * Constructor.
+ *
+ * @param selTree the current article
+ * @param selTarget the current section
+ */
+ public DecisionTreeTargetEditForm(ItemSelectionModel selTree,
+ ItemSelectionModel selTarget) {
+ this(selTree, selTarget, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param selArticle the current article
+ * @param selTarget the current section
+ * @param container container which this form is added to
+ */
+ public DecisionTreeTargetEditForm(ItemSelectionModel selTree,
+ ItemSelectionModel selTarget,
+ DecisionTreeViewTargets container) {
+ super("DecisionTreeTargetEditForm", new ColumnPanel(2));
+ m_selTree = selTree;
+ m_selTarget = selTarget;
+ m_container = container;
+
+ setMethod(Form.POST);
+ setEncType("multipart/form-data");
+
+ ColumnPanel panel = (ColumnPanel)getPanel();
+ panel.setBorder(false);
+ panel.setPadColor("#FFFFFF");
+ panel.setColumnWidth(1, "20%");
+ panel.setColumnWidth(2, "80%");
+ panel.setWidth("100%");
+
+ addWidgets();
+ addSaveCancelSection();
+
+ addInitListener(this);
+ addSubmissionListener(this);
+ addProcessListener(this);
+ }
+
+ /**
+ * Instantiate and add a save/cancel section to the form.
+ *
+ * @return the SaveCancelSection that was added
+ */
+ protected SaveCancelSection addSaveCancelSection() {
+ m_saveCancelSection = new SaveCancelSection();
+ add(m_saveCancelSection, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);
+ return m_saveCancelSection;
+ }
+
+ /**
+ * Returns the save/cancel section from this form.
+ */
+ public SaveCancelSection getSaveCancelSection() {
+ return m_saveCancelSection;
+ }
+
+ /**
+ * Set up the dynamic options for the section select widget.
+ */
+ private void initSectionOptions(PrintEvent e) {
+ PageState state = e.getPageState();
+ SingleSelect target = (SingleSelect) e.getTarget();
+ DecisionTree tree = (DecisionTree)m_selTree.getSelectedObject(state);
+
+ if (tree != null) {
+ DecisionTreeSectionCollection sections = tree.getSections();
+ if (sections != null) {
+ while (sections.next()) {
+ DecisionTreeSection section = sections.getSection();
+ Option option = new Option(section.getID().toString(),
+ section.getTitle());
+ target.addOption(option, state);
+ }
+ sections.close();
+ }
+ }
+ }
+
+ /**
+ * Set up the dynamic options for the target select widget.
+ */
+ private void initTargetOptions(PrintEvent e) {
+ PageState state = e.getPageState();
+ SingleSelect target = (SingleSelect) e.getTarget();
+ DecisionTree tree = (DecisionTree)m_selTree.getSelectedObject(state);
+
+ if (tree != null) {
+ DecisionTreeSectionCollection sections = tree.getSections();
+ if (sections != null) {
+ while (sections.next()) {
+ DecisionTreeSection section = sections.getSection();
+ Option option = new Option(section.getID().toString(),
+ section.getTitle());
+ target.addOption(option, state);
+ }
+ sections.close();
+ }
+ }
+ }
+
+ /**
+ * Set up the dynamic options for the match value select widget.
+ */
+ private void initMatchOptions(PrintEvent e) {
+ PageState state = e.getPageState();
+ SingleSelect target = (SingleSelect) e.getTarget();
+ DecisionTree tree = (DecisionTree)m_selTree.getSelectedObject(state);
+
+ if (tree != null) {
+ DecisionTreeSectionOptionCollection sectionOptions = tree.getOptions();
+ if (sectionOptions != null) {
+ while (sectionOptions.next()) {
+ DecisionTreeSectionOption sectionOption = sectionOptions.getOption();
+ String label = sectionOption.getSection().getTitle() + " : " + sectionOption.getLabel();
+ Option option = new Option(sectionOption.getID().toString(), label);
+ target.addOption(option, state);
+ }
+ sectionOptions.close();
+ }
+ }
+ }
+
+ /** Form initialisation hook. Sets the options for select widgets.
+ */
+ public void init(FormSectionEvent fse) {
+ PageState state = fse.getPageState();
+ FormData data = fse.getFormData();
+
+ if (m_selTarget.getSelectedKey(state) != null) {
+ BigDecimal id = new BigDecimal(m_selTarget.getSelectedKey(state).toString());
+ DecisionTreeOptionTarget target = new DecisionTreeOptionTarget(id);
+
+ data.put(MATCH_OPTION, target.getMatchOption().getID());
+ data.put(TARGET_URL, target.getTargetURL());
+
+ DecisionTreeSection targetSection = target.getTargetSection();
+ if (targetSection != null)
+ data.put(TARGET_SECTION, targetSection.getID());
+ }
+ }
+
+ /**
+ * Add form widgets for a Section.
+ */
+ protected void addWidgets() {
+ Option pleaseSelect = new Option("", (String)DecisionTreeUtil.globalize("form.please_select").localize());
+ Option none = new Option("", (String)DecisionTreeUtil.globalize("form.none").localize());
+
+ add(new Label(DecisionTreeUtil.globalize("form_label.match_value")));
+ m_matchValueWidget = new SingleSelect(MATCH_OPTION);
+ m_matchValueWidget.addValidationListener(new NotNullValidationListener());
+ m_matchValueWidget.addOption(pleaseSelect);
+
+ try {
+ m_matchValueWidget.addPrintListener(new PrintListener() {
+ public void prepare(PrintEvent e) {
+ initMatchOptions(e);
+ }
+ });
+ } catch (TooManyListenersException e) {
+ throw new RuntimeException(e);
+ }
+
+ add(m_matchValueWidget);
+
+ add(new Label(DecisionTreeUtil.globalize("form_label.target_url")));
+ m_targetURLWidget = new TextField(TARGET_URL);
+ m_targetURLWidget.setSize(60);
+ add(m_targetURLWidget);
+
+ add(new Label(DecisionTreeUtil.globalize("form_label.target_section")));
+ m_targetSectionWidget = new SingleSelect(TARGET_SECTION);
+ m_targetSectionWidget.addOption(none);
+
+ try {
+ m_targetSectionWidget.addPrintListener(new PrintListener() {
+ public void prepare(PrintEvent e) {
+ initTargetOptions(e);
+ }
+ });
+ } catch (TooManyListenersException e) {
+ throw new RuntimeException(e);
+ }
+
+ add(m_targetSectionWidget);
+
+ addValidationListener(new FormValidationListener() {
+ public final void validate(final FormSectionEvent event)
+ throws FormProcessException {
+ final PageState state = event.getPageState();
+ if ("".equals(m_targetURLWidget.getValue(state)) && "".equals(m_targetSectionWidget.getValue(state))) {
+ String msg = (String) DecisionTreeUtil.globalize("form_validation.target_required").localize();
+ throw new FormProcessException(msg);
+ }
+
+ if (!"".equals(m_targetURLWidget.getValue(state)) && !"".equals(m_targetSectionWidget.getValue(state))) {
+ String msg = (String) DecisionTreeUtil.globalize("form_validation.duplicate_target").localize();
+ throw new FormProcessException(msg);
+ }
+ }
+ });
+ }
+
+ /**
+ * Called on form submission. Check to see if the user clicked the
+ * cancel button. If they did, don't continue with the form.
+ */
+ public void submitted(FormSectionEvent event)
+ throws FormProcessException {
+ PageState state = event.getPageState();
+
+ if ( m_saveCancelSection.getCancelButton()
+ .isSelected(state) && m_container != null) {
+ m_container.onlyShowComponent(
+ state, DecisionTreeViewTargets.TARGET_TABLE +
+ m_container.getTypeIDStr());
+ throw new FormProcessException(
+ (String)DecisionTreeUtil
+ .globalize("tree_section.submission_cancelled")
+ .localize());
+ }
+ }
+
+ /**
+ * Called after form has been validated. Create the new DecisionTreeOptionTarget and
+ * assign it to the current DecisionTree.
+ */
+ public void process(FormSectionEvent event) throws FormProcessException {
+ PageState state = event.getPageState();
+ FormData data = event.getFormData();
+
+ DecisionTreeSectionOption matchOption = new
+ DecisionTreeSectionOption(new
+ BigDecimal((String)data.get(MATCH_OPTION)));
+
+ DecisionTreeSection targetSection = null;
+ String sectionID = (String)data.get(TARGET_SECTION);
+ if (!"".equals(sectionID)) {
+ targetSection = new DecisionTreeSection(new BigDecimal(sectionID));
+ }
+
+ DecisionTreeOptionTarget target = null;
+ if (m_selTarget.getSelectedKey(state) != null) {
+ BigDecimal id = new BigDecimal(m_selTarget
+ .getSelectedKey(state).toString());
+ target = new DecisionTreeOptionTarget(id);
+ } else {
+ target = new DecisionTreeOptionTarget();
+ target.setName("OptionTarget " + target.getID());
+ }
+
+ target.setMatchOption(matchOption);
+ target.setTargetURL((String)data.get(TARGET_URL));
+ target.setTargetSection(targetSection);
+
+ if (m_container != null) {
+ m_container.onlyShowComponent(
+ state,
+ DecisionTreeViewTargets.TARGET_TABLE +
+ m_container.getTypeIDStr());
+ }
+ }
+
+ public void register(Page p) {
+ super.register(p);
+ }
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeTargetTable.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeTargetTable.java
new file mode 100644
index 000000000..3bb0d5c13
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeTargetTable.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+
+import org.apache.log4j.Logger;
+
+import com.arsdigita.bebop.Component;
+import com.arsdigita.bebop.ControlLink;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.Table;
+import com.arsdigita.bebop.table.TableCellRenderer;
+import com.arsdigita.bebop.table.TableColumn;
+import com.arsdigita.bebop.table.TableColumnModel;
+import com.arsdigita.bebop.table.TableModel;
+import com.arsdigita.bebop.table.TableModelBuilder;
+import com.arsdigita.cms.contenttypes.DecisionTree;
+import com.arsdigita.cms.contenttypes.DecisionTreeOptionTarget;
+import com.arsdigita.cms.contenttypes.DecisionTreeOptionTargetCollection;
+import com.arsdigita.cms.ContentItem;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.SecurityManager;
+import com.arsdigita.cms.dispatcher.Utilities;
+import com.arsdigita.util.LockableImpl;
+
+
+/**
+ * A table that displays the targets for the currently
+ * selected DecisionTree.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeTargetTable extends Table
+{
+ private static final Logger s_log = Logger.getLogger(
+ DecisionTreeTargetTable.class);
+
+ // column headings
+ public static final String COL_SECTION = "Section";
+ public static final String COL_MATCH = "Match";
+ public static final String COL_EDIT = "Edit";
+ public static final String COL_DEL = "Delete";
+
+ private ItemSelectionModel m_selTree;
+
+ /**
+ * Constructor.
+ *
+ * @param selArticle a selection model that returns the MultiPartArticle
+ * which holds the sections to display.
+ */
+ public DecisionTreeTargetTable(ItemSelectionModel selArticle) {
+ super();
+ m_selTree = selArticle;
+
+ TableColumnModel model = getColumnModel();
+ model.add(new TableColumn(0, COL_SECTION));
+ model.add(new TableColumn(1, COL_MATCH));
+ model.add(new TableColumn(2, COL_EDIT));
+ model.add(new TableColumn(3, COL_DEL));
+
+ model.get(2).setCellRenderer(new SectionTableCellRenderer(true));
+ model.get(3).setCellRenderer(new SectionTableCellRenderer(true));
+
+ setModelBuilder(new OptionTableModelBuilder(m_selTree));
+ }
+
+ /**
+ *
+ * @param selSection
+ */
+ public void setSectionModel(ItemSelectionModel selSection) {
+ if (selSection == null) {
+ s_log.warn("null item model");
+ }
+ }
+
+ /**
+ * The model builder to generate a suitable model for the OptionTable
+ */
+ protected class OptionTableModelBuilder extends LockableImpl
+ implements TableModelBuilder
+ {
+ protected ItemSelectionModel m_selTree;
+
+ public OptionTableModelBuilder(ItemSelectionModel selTree) {
+ m_selTree = selTree;
+ }
+
+ public TableModel makeModel(Table table, PageState state) {
+ table.getRowSelectionModel().clearSelection(state);
+ DecisionTree tree = (DecisionTree)m_selTree.getSelectedObject(state);
+ return new TargetTableModel(table, state, tree);
+ }
+ }
+
+ /**
+ *
+ */
+ protected class TargetTableModel implements TableModel
+ {
+ private TableColumnModel m_colModel;
+ private DecisionTreeOptionTargetCollection m_targets;
+ private DecisionTreeOptionTarget m_target;
+
+ /** Constructor. */
+ public TargetTableModel(Table table, PageState state, DecisionTree tree) {
+ m_colModel = table.getColumnModel();
+ m_targets = tree.getTargets();
+ }
+
+ /** Return the number of columsn this TableModel has. */
+ public int getColumnCount() {
+ return m_colModel.size();
+ }
+
+ /** Move to the next row and return true if the model is now positioned on
+ * a valid row.
+ */
+ public boolean nextRow() {
+ if (m_targets.next()) {
+ m_target = (DecisionTreeOptionTarget) m_targets.getTarget();
+ return true;
+ }
+ return false;
+ }
+
+ /** Return the data element for the given column and the current row. */
+ public Object getElementAt(int columnIndex) {
+ if (m_colModel == null) { return null; }
+
+ // match columns by name... makes for easier reordering
+ TableColumn col = m_colModel.get(columnIndex);
+ String colName = (String) col.getHeaderValue();
+
+ if (COL_SECTION.equals(colName)) {
+ return m_target.getMatchOption().getSection().getTitle();
+ } else if (COL_MATCH.equals(colName)) {
+ return m_target.getMatchOption().getLabel();
+ } else if (COL_EDIT.equals(colName)) {
+ return "edit";
+ } else if (COL_DEL.equals(colName)) {
+ return "delete";
+ }
+
+ return null;
+ }
+
+ /** Return the key for the given column and the current row. */
+ public Object getKeyAt(int columnIndex) {
+ return m_target.getID();
+ }
+ }
+
+ /**
+ *
+ */
+ public class SectionTableCellRenderer extends LockableImpl
+ implements TableCellRenderer
+ {
+ /** */
+ private boolean m_active;
+
+ /** */
+ public SectionTableCellRenderer () {
+ this(false);
+ }
+
+ /** */
+ public SectionTableCellRenderer(boolean active) {
+ m_active = active;
+ }
+
+ /** */
+ public Component getComponent(Table table, PageState state,
+ Object value, boolean isSelected,
+ Object key, int row, int column) {
+ Component ret = null;
+ SecurityManager sm = Utilities.getSecurityManager(state);
+ ContentItem item = (ContentItem)m_selTree.getSelectedObject(state);
+
+ boolean active = m_active &&
+ sm.canAccess(state.getRequest(), SecurityManager.EDIT_ITEM,
+ item);
+
+ if (value instanceof Component) {
+ ret = (Component)value;
+ } else {
+ if (value == null) {
+ ret = new Label("", false);
+ } else {
+ if (active) {
+ ret = new ControlLink(value.toString());
+ } else {
+ ret = new Label(value.toString());
+ }
+ }
+ }
+
+ return ret;
+ }
+ }
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeViewOptions.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeViewOptions.java
new file mode 100644
index 000000000..c8ab28ddf
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeViewOptions.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+
+import java.math.BigDecimal;
+
+import com.arsdigita.bebop.ActionLink;
+import com.arsdigita.bebop.ColumnPanel;
+import com.arsdigita.bebop.Container;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.Page;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.event.ActionEvent;
+import com.arsdigita.bebop.event.ActionListener;
+import com.arsdigita.bebop.event.ChangeEvent;
+import com.arsdigita.bebop.event.ChangeListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.event.FormSubmissionListener;
+import com.arsdigita.bebop.event.PrintEvent;
+import com.arsdigita.bebop.event.PrintListener;
+import com.arsdigita.bebop.event.TableActionEvent;
+import com.arsdigita.bebop.event.TableActionListener;
+import com.arsdigita.bebop.parameters.BigDecimalParameter;
+import com.arsdigita.bebop.table.TableColumn;
+import com.arsdigita.cms.contenttypes.DecisionTree;
+import com.arsdigita.cms.contenttypes.DecisionTreeUtil;
+import com.arsdigita.cms.contenttypes.DecisionTreeSectionOption;
+import com.arsdigita.cms.contenttypes.DecisionTreeSection;
+import com.arsdigita.cms.ContentItem;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.SecurityManager;
+import com.arsdigita.cms.contenttypes.ui.ResettableContainer;
+import com.arsdigita.cms.dispatcher.Utilities;
+import com.arsdigita.cms.ui.authoring.AuthoringKitWizard;
+import com.arsdigita.util.Assert;
+
+
+/**
+ * Authoring kit step to manage the options for a DecisionTree.
+ * The editing process is implemented with three main visual components
+ * that manipulate the currently selected DecisionTree and options.
+ * The visibility of these components is managed by this class.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeViewOptions extends ResettableContainer
+{
+ /** id keys for each editing panel */
+ public static final String OPTION_TABLE = "opt_tbl";
+ public static final String OPTION_EDIT = "opt_edt";
+ public static final String OPTION_DEL = "opt_del";
+
+ /** class attributes */
+ public static final String DATA_TABLE = "dataTable";
+ public static final String ACTION_LINK = "actionLink";
+
+ protected AuthoringKitWizard m_wizard;
+ protected ItemSelectionModel m_selTree;
+ protected ItemSelectionModel m_selOption;
+ protected ItemSelectionModel m_moveOption;
+ protected BigDecimalParameter m_moveParameter;
+
+ /** visual components that do the 'real work' */
+ protected DecisionTreeOptionTable m_optionTable;
+ protected DecisionTreeOptionEditForm m_optionEdit;
+ protected DecisionTreeOptionDeleteForm m_optionDelete;
+
+ protected ActionLink m_beginLink;
+ private Label m_moveOptionLabel;
+
+ private String m_typeIDStr;
+
+ public DecisionTreeViewOptions (ItemSelectionModel selTree, AuthoringKitWizard wizard) {
+ super();
+ m_selTree = selTree;
+ m_wizard = wizard;
+ m_typeIDStr = wizard.getContentType().getID().toString();
+ Assert.exists(m_selTree, ItemSelectionModel.class);
+
+ // create the components and set default visibility
+ add(buildOptionTable(), true);
+ add(buildOptionEdit(), false);
+ add(buildOptionDelete(), false);
+ }
+
+ /**
+ * Builds a container to hold an OptionTable and a link
+ * to add a new option.
+ */
+ protected Container buildOptionTable () {
+ ColumnPanel c = new ColumnPanel(1);
+ c.setKey(OPTION_TABLE+m_typeIDStr);
+ c.setBorderColor("#FFFFFF");
+ c.setPadColor("#FFFFFF");
+
+ m_moveParameter = new BigDecimalParameter("moveOption");
+ m_moveOption = new ItemSelectionModel(DecisionTreeSectionOption.class.getName(),
+ DecisionTreeSectionOption.BASE_DATA_OBJECT_TYPE,
+ m_moveParameter);
+
+ m_optionTable = new DecisionTreeOptionTable(m_selTree, m_moveOption);
+ m_optionTable.setClassAttr(DATA_TABLE);
+
+ // selected option is based on the selection in the OptionTable
+ m_selOption = new ItemSelectionModel(DecisionTreeSectionOption.class.getName(),
+ DecisionTreeSectionOption.BASE_DATA_OBJECT_TYPE,
+ m_optionTable.getRowSelectionModel());
+ m_optionTable.setOptionModel(m_selOption);
+
+ Label emptyView = new Label(DecisionTreeUtil
+ .globalize("section_options.no_options_yet"));
+ m_optionTable.setEmptyView(emptyView);
+
+ m_moveOptionLabel = new Label ("Option Name");
+ c.add(m_moveOptionLabel, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);
+
+ m_beginLink = new ActionLink(DecisionTreeUtil
+ .globalize("section_options.move_to_beginning"));
+ c.add(m_beginLink);
+
+ m_beginLink.addActionListener ( new ActionListener() {
+ public void actionPerformed ( ActionEvent event ) {
+ PageState state = event.getPageState();
+ DecisionTreeSectionOption option = new
+ DecisionTreeSectionOption((BigDecimal) m_moveOption
+ .getSelectedKey(state));
+
+ option.getSection().changeOptionRank(option, 1);
+ option.save();
+ m_moveOption.setSelectedKey(state, null);
+ }
+ });
+
+ m_moveOption.addChangeListener ( new ChangeListener () {
+ public void stateChanged ( ChangeEvent e ) {
+ PageState state = e.getPageState();
+ if ( m_moveOption.getSelectedKey(state) == null ) {
+ m_beginLink.setVisible(state, false);
+ m_moveOptionLabel.setVisible(state, false);
+ } else {
+ m_beginLink.setVisible(state, true);
+ m_moveOptionLabel.setVisible(state, true);
+
+ DecisionTreeSectionOption option =
+ (DecisionTreeSectionOption) m_moveOption
+ .getSelectedObject(state);
+ String optionName = option.getSection().getTitle() + " - "
+ + option.getLabel();
+
+ m_moveOptionLabel.setLabel
+ ( (String)DecisionTreeUtil
+ .globalize("section_options.move_option_name")
+ .localize()
+ + " \"" + optionName + "\"", state);
+ }
+ }
+ });
+
+ // handle clicks to preview or delete a Section
+ m_optionTable.addTableActionListener (new TableActionListener () {
+ public void cellSelected (TableActionEvent event) {
+ PageState state = event.getPageState();
+
+ TableColumn col = m_optionTable.getColumnModel()
+ .get(event.getColumn().intValue());
+ String colName = (String)col.getHeaderValue();
+
+ if (DecisionTreeOptionTable.COL_DEL.equals(colName)) {
+ onlyShowComponent(state, OPTION_DEL+m_typeIDStr);
+ } else if (DecisionTreeOptionTable.COL_EDIT.equals(colName)) {
+ onlyShowComponent(state, OPTION_EDIT+m_typeIDStr);
+ }
+ }
+
+ public void headSelected(TableActionEvent e) {}
+ });
+ c.add(m_optionTable);
+
+ // link to add new section
+ c.add(buildAddLink());
+
+ return c;
+ }
+
+ /**
+ * Builds a container to hold a SectionEditForm and a link
+ * to return to the section list.
+ */
+ protected Container buildOptionEdit () {
+ ColumnPanel c = new ColumnPanel(1);
+ c.setKey(OPTION_EDIT+m_typeIDStr);
+ c.setBorderColor("#FFFFFF");
+ c.setPadColor("#FFFFFF");
+
+ // display an appropriate title
+ c.add( new Label( new PrintListener() {
+ public void prepare ( PrintEvent event ) {
+ PageState state = event.getPageState();
+ Label label = (Label)event.getTarget();
+
+ if (m_selOption.getSelectedKey(state) == null) {
+ label.setLabel((String)DecisionTreeUtil.globalize("section_options.add_option").localize());
+ } else {
+ label.setLabel((String)DecisionTreeUtil.globalize("section_options.edit_option").localize());
+ }
+ }
+ }));
+
+ // form to edit a Section
+ m_optionEdit = new DecisionTreeOptionEditForm(m_selTree, m_selOption, this);
+ c.add(m_optionEdit);
+
+ c.add(buildViewAllLink());
+ // link to add new section
+ c.add(buildAddLink());
+
+ return c;
+ }
+
+ /**
+ * Builds a container to hold the component to confirm
+ * deletion of a section.
+ */
+ protected Container buildOptionDelete () {
+ ColumnPanel c = new ColumnPanel(1);
+ c.setKey(OPTION_DEL+m_typeIDStr);
+ c.setBorderColor("#FFFFFF");
+ c.setPadColor("#FFFFFF");
+
+ c.add(new Label(DecisionTreeUtil.globalize("section_options.delete_option")));
+ m_optionDelete = new DecisionTreeOptionDeleteForm(m_selTree, m_selOption);
+ m_optionDelete.addSubmissionListener ( new FormSubmissionListener () {
+ public void submitted ( FormSectionEvent e ) {
+ PageState state = e.getPageState();
+ onlyShowComponent(state, OPTION_TABLE+m_typeIDStr);
+ }
+ });
+ c.add(m_optionDelete);
+
+ c.add(buildViewAllLink());
+
+ return c;
+ }
+
+ /**
+ * Utility method to create a link to display the section list.
+ */
+ protected ActionLink buildViewAllLink () {
+ ActionLink viewAllLink = new ActionLink( (String) DecisionTreeUtil.globalize("section_options.view_all_options").localize());
+ viewAllLink.setClassAttr(ACTION_LINK);
+ viewAllLink.addActionListener( new ActionListener() {
+ public void actionPerformed ( ActionEvent event ) {
+ onlyShowComponent(event.getPageState(), OPTION_TABLE+m_typeIDStr);
+ }
+ });
+
+ return viewAllLink;
+ }
+
+ /**
+ * Utility method to create a link to display the section list.
+ */
+ protected ActionLink buildAddLink () {
+ ActionLink addLink = new ActionLink( (String) DecisionTreeUtil.globalize("section_options.add_new_option").localize()) {
+ public boolean isVisible(PageState state) {
+ SecurityManager sm = Utilities.getSecurityManager(state);
+ ContentItem item = (ContentItem)m_selTree.getSelectedObject(state);
+
+ return super.isVisible(state) &&
+ sm.canAccess(state.getRequest(), SecurityManager.EDIT_ITEM,
+ item);
+
+ }
+ };
+ addLink.setClassAttr(ACTION_LINK);
+ addLink.addActionListener( new ActionListener () {
+ public void actionPerformed ( ActionEvent event ) {
+ PageState state = event.getPageState();
+ m_selOption.clearSelection(state);
+ onlyShowComponent(state, OPTION_EDIT+m_typeIDStr);
+ }
+ });
+
+ return addLink;
+ }
+
+ public void register ( Page p ) {
+ super.register(p);
+ p.addGlobalStateParam(m_moveParameter);
+ p.setVisibleDefault(m_beginLink, false);
+ p.setVisibleDefault(m_moveOptionLabel, false);
+ }
+
+ public String getTypeIDStr() {
+ return m_typeIDStr;
+ }
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeViewSections.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeViewSections.java
new file mode 100644
index 000000000..d27d6f8b1
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeViewSections.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+
+import com.arsdigita.bebop.ActionLink;
+import com.arsdigita.bebop.ColumnPanel;
+import com.arsdigita.bebop.Container;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.event.ActionEvent;
+import com.arsdigita.bebop.event.ActionListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.event.FormSubmissionListener;
+import com.arsdigita.bebop.event.PrintEvent;
+import com.arsdigita.bebop.event.PrintListener;
+import com.arsdigita.bebop.event.TableActionEvent;
+import com.arsdigita.bebop.event.TableActionListener;
+import com.arsdigita.bebop.table.TableColumn;
+import com.arsdigita.cms.contenttypes.DecisionTree;
+import com.arsdigita.cms.contenttypes.DecisionTreeUtil;
+import com.arsdigita.cms.contenttypes.DecisionTreeSection;
+import com.arsdigita.cms.ContentItem;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.SecurityManager;
+import com.arsdigita.cms.contenttypes.ui.ResettableContainer;
+import com.arsdigita.cms.dispatcher.Utilities;
+import com.arsdigita.cms.ui.authoring.AuthoringKitWizard;
+import com.arsdigita.util.Assert;
+
+
+/**
+ * Authoring kit step to manage the sections for a DecisionTree.
+ * The editing process is implemented with three main visual components
+ * that manipulate the currently selected DecisionTree and sections.
+ * The visibility of these components is managed by this class.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeViewSections extends ResettableContainer
+{
+ /** id keys for each editing panel */
+ public static final String SECTION_TABLE = "sec_tbl";
+ public static final String SECTION_EDIT = "sec_edt";
+ public static final String SECTION_DEL = "sec_del";
+
+ /** class attributes */
+ public static final String DATA_TABLE = "dataTable";
+ public static final String ACTION_LINK = "actionLink";
+
+ protected AuthoringKitWizard m_wizard;
+ protected ItemSelectionModel m_selTree;
+ protected ItemSelectionModel m_selSection;
+
+ /** visual components that do the 'real work' */
+ protected DecisionTreeSectionTable m_sectionTable;
+ protected DecisionTreeSectionEditForm m_sectionEdit;
+ protected DecisionTreeSectionDeleteForm m_sectionDelete;
+
+ private String m_typeIDStr;
+
+ public DecisionTreeViewSections (ItemSelectionModel selTree,
+ AuthoringKitWizard wizard) {
+ super();
+ m_selTree = selTree;
+ m_wizard = wizard;
+ m_typeIDStr = wizard.getContentType().getID().toString();
+ Assert.exists(m_selTree, ItemSelectionModel.class);
+
+ // create the components and set default visibility
+ add(buildSectionTable(), true);
+ add(buildSectionEdit(), false);
+ add(buildSectionDelete(), false);
+ }
+
+ /**
+ * Builds a container to hold a SectionTable and a link
+ * to add a new section.
+ */
+ protected Container buildSectionTable () {
+ ColumnPanel c = new ColumnPanel(1);
+ c.setKey(SECTION_TABLE+m_typeIDStr);
+ c.setBorderColor("#FFFFFF");
+ c.setPadColor("#FFFFFF");
+
+ m_sectionTable = new DecisionTreeSectionTable(m_selTree);
+ m_sectionTable.setClassAttr(DATA_TABLE);
+
+ // selected section is based on the selection in the SectionTable
+ m_selSection = new ItemSelectionModel(DecisionTreeSection.class.getName(),
+ DecisionTreeSection.BASE_DATA_OBJECT_TYPE,
+ m_sectionTable.getRowSelectionModel());
+
+ m_sectionTable.setSectionModel(m_selSection);
+
+ Label emptyView = new Label(DecisionTreeUtil
+ .globalize("tree_sections.no_sections_yet"));
+ m_sectionTable.setEmptyView(emptyView);
+
+ // handle clicks to delete a Section
+ m_sectionTable.addTableActionListener (new TableActionListener () {
+ public void cellSelected (TableActionEvent event) {
+ PageState state = event.getPageState();
+
+ TableColumn col = m_sectionTable.getColumnModel()
+ .get(event.getColumn().intValue());
+ String colName = (String)col.getHeaderValue();
+
+ if (DecisionTreeSectionTable.COL_DEL.equals(colName)) {
+ onlyShowComponent(state, SECTION_DEL+m_typeIDStr);
+ } else if (DecisionTreeSectionTable.COL_EDIT.equals(colName)) {
+ onlyShowComponent(state, SECTION_EDIT+m_typeIDStr);
+ } else if (DecisionTreeSectionTable.COL_FIRST.equals(colName)) {
+ DecisionTree tree = (DecisionTree)m_selTree
+ .getSelectedObject(state);
+ DecisionTreeSection section = (DecisionTreeSection)m_selSection
+ .getSelectedItem(state);
+ tree.setFirstSection(section);
+ tree.save();
+ }
+ }
+
+ public void headSelected(TableActionEvent e) {}
+ });
+ c.add(m_sectionTable);
+
+ // link to add new section
+ c.add(buildAddLink());
+
+ return c;
+ }
+
+ /**
+ * Builds a container to hold a SectionEditForm and a link
+ * to return to the section list.
+ */
+ protected Container buildSectionEdit () {
+ ColumnPanel c = new ColumnPanel(1);
+ c.setKey(SECTION_EDIT+m_typeIDStr);
+ c.setBorderColor("#FFFFFF");
+ c.setPadColor("#FFFFFF");
+
+ // display an appropriate title
+ c.add( new Label( new PrintListener() {
+ public void prepare ( PrintEvent event ) {
+ PageState state = event.getPageState();
+ Label label = (Label)event.getTarget();
+
+ if (m_selSection.getSelectedKey(state) == null) {
+ label.setLabel(DecisionTreeUtil
+ .globalize("tree_sections.add_section"));
+ } else {
+ label.setLabel(DecisionTreeUtil
+ .globalize("tree_sections.edit_section"));
+ }
+ }
+ }));
+
+ // form to edit a Section
+ m_sectionEdit = new DecisionTreeSectionEditForm(m_selTree, m_selSection, this);
+ c.add(m_sectionEdit);
+
+ c.add(buildViewAllLink());
+ // link to add new section
+ c.add(buildAddLink());
+
+ return c;
+ }
+
+ /**
+ * Builds a container to hold the component to confirm
+ * deletion of a section.
+ */
+ protected Container buildSectionDelete () {
+ ColumnPanel c = new ColumnPanel(1);
+ c.setKey(SECTION_DEL+m_typeIDStr);
+ c.setBorderColor("#FFFFFF");
+ c.setPadColor("#FFFFFF");
+
+ c.add(new Label(DecisionTreeUtil.globalize("tree_sections.delete_section")));
+ m_sectionDelete = new DecisionTreeSectionDeleteForm(m_selTree, m_selSection);
+ m_sectionDelete.addSubmissionListener ( new FormSubmissionListener () {
+ public void submitted ( FormSectionEvent e ) {
+ PageState state = e.getPageState();
+ onlyShowComponent(state, SECTION_TABLE+m_typeIDStr);
+ }
+ });
+ c.add(m_sectionDelete);
+
+ c.add(buildViewAllLink());
+
+ return c;
+ }
+
+ /**
+ * Utility method to create a link to display the section list.
+ */
+ protected ActionLink buildViewAllLink () {
+ ActionLink viewAllLink = new ActionLink(DecisionTreeUtil
+ .globalize("tree_sections.view_all_sections"));
+ viewAllLink.setClassAttr(ACTION_LINK);
+ viewAllLink.addActionListener( new ActionListener() {
+ public void actionPerformed ( ActionEvent event ) {
+ onlyShowComponent(event.getPageState(), SECTION_TABLE+m_typeIDStr);
+ }
+ });
+
+ return viewAllLink;
+ }
+
+ /**
+ * Utility method to create a link to display the section list.
+ */
+ protected ActionLink buildAddLink () {
+ ActionLink addLink = new ActionLink(DecisionTreeUtil
+ .globalize("tree_sections.add_new_section")) {
+ @Override
+ public boolean isVisible(PageState state) {
+ SecurityManager sm = Utilities.getSecurityManager(state);
+ ContentItem item = (ContentItem)m_selTree.getSelectedObject(state);
+
+ return super.isVisible(state) &&
+ sm.canAccess(state.getRequest(), SecurityManager.EDIT_ITEM,
+ item);
+
+ }
+ };
+ addLink.setClassAttr(ACTION_LINK);
+ addLink.addActionListener( new ActionListener () {
+ public void actionPerformed ( ActionEvent event ) {
+ PageState state = event.getPageState();
+ m_selSection.clearSelection(state);
+ onlyShowComponent(state, SECTION_EDIT+m_typeIDStr);
+ }
+ });
+
+ return addLink;
+ }
+
+ public String getTypeIDStr() {
+ return m_typeIDStr;
+ }
+}
diff --git a/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeViewTargets.java b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeViewTargets.java
new file mode 100644
index 000000000..c746e9e24
--- /dev/null
+++ b/ccm-cms-types-decisiontree/src/com/arsdigita/cms/contenttypes/ui/DecisionTreeViewTargets.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2007 Red Hat Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+package com.arsdigita.cms.contenttypes.ui;
+
+
+import com.arsdigita.bebop.ActionLink;
+import com.arsdigita.bebop.ColumnPanel;
+import com.arsdigita.bebop.Container;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.event.ActionEvent;
+import com.arsdigita.bebop.event.ActionListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.event.FormSubmissionListener;
+import com.arsdigita.bebop.event.PrintEvent;
+import com.arsdigita.bebop.event.PrintListener;
+import com.arsdigita.bebop.event.TableActionEvent;
+import com.arsdigita.bebop.event.TableActionListener;
+import com.arsdigita.bebop.table.TableColumn;
+import com.arsdigita.cms.contenttypes.DecisionTree;
+import com.arsdigita.cms.contenttypes.DecisionTreeUtil;
+import com.arsdigita.cms.contenttypes.DecisionTreeSection;
+import com.arsdigita.cms.ContentItem;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.SecurityManager;
+import com.arsdigita.cms.contenttypes.ui.ResettableContainer;
+import com.arsdigita.cms.dispatcher.Utilities;
+import com.arsdigita.cms.ui.authoring.AuthoringKitWizard;
+import com.arsdigita.util.Assert;
+
+
+/**
+ * Authoring kit step to manage the targets for a DecisionTree.
+ * The editing process is implemented with three main visual components
+ * that manipulate the currently selected DecisionTree and targets.
+ * The visibility of these components is managed by this class.
+ *
+ * @author Carsten Clasohm
+ * @version $Id$
+ */
+public class DecisionTreeViewTargets extends ResettableContainer
+{
+ /** id keys for each editing panel */
+ public static final String TARGET_TABLE = "tgt_tbl";
+ public static final String TARGET_EDIT = "tgt_edt";
+ public static final String TARGET_DEL = "tgt_del";
+
+ /** class attributes */
+ public static final String DATA_TABLE = "dataTable";
+ public static final String ACTION_LINK = "actionLink";
+
+ protected AuthoringKitWizard m_wizard;
+ protected ItemSelectionModel m_selTree;
+ protected ItemSelectionModel m_selTarget;
+
+ /** visual components that do the 'real work' */
+ protected DecisionTreeTargetTable m_targetTable;
+ protected DecisionTreeTargetEditForm m_targetEdit;
+ protected DecisionTreeTargetDeleteForm m_targetDelete;
+
+ private String m_typeIDStr;
+
+ /**
+ *
+ * @param selTree
+ * @param wizard
+ */
+ public DecisionTreeViewTargets (ItemSelectionModel selTree,
+ AuthoringKitWizard wizard) {
+ super();
+ m_selTree = selTree;
+ m_wizard = wizard;
+ m_typeIDStr = wizard.getContentType().getID().toString();
+ Assert.exists(m_selTree, ItemSelectionModel.class);
+
+ // create the components and set default visibility
+ add(buildTargetTable(), true);
+ add(buildTargetEdit(), false);
+ add(buildTargetDelete(), false);
+ }
+
+ /**
+ * Builds a container to hold a TargetTable and a link
+ * to add a new target.
+ */
+ protected Container buildTargetTable () {
+ ColumnPanel c = new ColumnPanel(1);
+ c.setKey(TARGET_TABLE+m_typeIDStr);
+ c.setBorderColor("#FFFFFF");
+ c.setPadColor("#FFFFFF");
+
+ m_targetTable = new DecisionTreeTargetTable(m_selTree);
+ m_targetTable.setClassAttr(DATA_TABLE);
+
+ // selected section is based on the selection in the SectionTable
+ m_selTarget = new ItemSelectionModel(DecisionTreeSection.class.getName(),
+ DecisionTreeSection.BASE_DATA_OBJECT_TYPE,
+ m_targetTable.getRowSelectionModel());
+
+ m_targetTable.setSectionModel(m_selTarget);
+
+ Label emptyView = new Label(DecisionTreeUtil
+ .globalize("option_targets.no_targets_yet"));
+ m_targetTable.setEmptyView(emptyView);
+
+ // handle clicks to preview or delete a Section
+ m_targetTable.addTableActionListener (new TableActionListener () {
+ public void cellSelected (TableActionEvent event) {
+ PageState state = event.getPageState();
+
+ TableColumn col = m_targetTable.getColumnModel()
+ .get(event.getColumn().intValue());
+ String colName = (String)col.getHeaderValue();
+
+ if (DecisionTreeSectionTable.COL_DEL.equals(colName)) {
+ onlyShowComponent(state, TARGET_DEL+m_typeIDStr);
+ } else if (DecisionTreeSectionTable.COL_EDIT.equals(colName)) {
+ onlyShowComponent(state, TARGET_EDIT+m_typeIDStr);
+ } else if (DecisionTreeSectionTable.COL_FIRST.equals(colName)) {
+ DecisionTree tree =
+ (DecisionTree)m_selTree.getSelectedObject(state);
+ DecisionTreeSection section =
+ (DecisionTreeSection)m_selTarget.getSelectedItem(state);
+ tree.setFirstSection(section);
+ tree.save();
+ }
+ }
+
+ public void headSelected(TableActionEvent e) {}
+ });
+ c.add(m_targetTable);
+
+ // link to add new section
+ c.add(buildAddLink());
+
+ return c;
+ }
+
+ /**
+ * Builds a container to hold a SectionEditForm and a link
+ * to return to the section list.
+ */
+ protected Container buildTargetEdit () {
+ ColumnPanel c = new ColumnPanel(1);
+ c.setKey(TARGET_EDIT+m_typeIDStr);
+ c.setBorderColor("#FFFFFF");
+ c.setPadColor("#FFFFFF");
+
+ // display an appropriate title
+ c.add( new Label( new PrintListener() {
+ public void prepare ( PrintEvent event ) {
+ PageState state = event.getPageState();
+ Label label = (Label)event.getTarget();
+
+ if (m_selTarget.getSelectedKey(state) == null) {
+ label.setLabel(DecisionTreeUtil
+ .globalize("option_targets.add_target"));
+ } else {
+ label.setLabel(DecisionTreeUtil
+ .globalize("option_targets.edit_target"));
+ }
+ }
+ }));
+
+ // form to edit a Section
+ m_targetEdit = new DecisionTreeTargetEditForm(m_selTree, m_selTarget, this);
+ c.add(m_targetEdit);
+
+ c.add(buildViewAllLink());
+ // link to add new section
+ c.add(buildAddLink());
+
+ return c;
+ }
+
+ /**
+ * Builds a container to hold the component to confirm
+ * deletion of a section.
+ */
+ protected Container buildTargetDelete () {
+ ColumnPanel c = new ColumnPanel(1);
+ c.setKey(TARGET_DEL+m_typeIDStr);
+ c.setBorderColor("#FFFFFF");
+ c.setPadColor("#FFFFFF");
+
+ c.add(new Label(DecisionTreeUtil.globalize("option_targets.delete_target")));
+ m_targetDelete = new DecisionTreeTargetDeleteForm(m_selTree, m_selTarget);
+ m_targetDelete.addSubmissionListener ( new FormSubmissionListener () {
+ public void submitted ( FormSectionEvent e ) {
+ PageState state = e.getPageState();
+ onlyShowComponent(state, TARGET_TABLE+m_typeIDStr);
+ }
+ });
+ c.add(m_targetDelete);
+
+ c.add(buildViewAllLink());
+
+ return c;
+ }
+
+ /**
+ * Utility method to create a link to display the section list.
+ */
+ protected ActionLink buildViewAllLink () {
+ ActionLink viewAllLink = new
+ ActionLink( DecisionTreeUtil.globalize("option_targets.view_all_targets"));
+ viewAllLink.setClassAttr(ACTION_LINK);
+ viewAllLink.addActionListener( new ActionListener() {
+ public void actionPerformed ( ActionEvent event ) {
+ onlyShowComponent(event.getPageState(), TARGET_TABLE+m_typeIDStr);
+ }
+ });
+
+ return viewAllLink;
+ }
+
+ /**
+ * Utility method to create a link to display the section list.
+ */
+ protected ActionLink buildAddLink () {
+
+ ActionLink addLink = new ActionLink( DecisionTreeUtil
+ .globalize("option_targets.add_new_target")) {
+ @Override
+ public boolean isVisible(PageState state) {
+ SecurityManager sm = Utilities.getSecurityManager(state);
+ ContentItem item = (ContentItem)m_selTree.getSelectedObject(state);
+
+ return super.isVisible(state) &&
+ sm.canAccess(state.getRequest(), SecurityManager.EDIT_ITEM,
+ item);
+
+ }
+ };
+ addLink.setClassAttr(ACTION_LINK);
+ addLink.addActionListener( new ActionListener () {
+ public void actionPerformed ( ActionEvent event ) {
+ PageState state = event.getPageState();
+ m_selTarget.clearSelection(state);
+ onlyShowComponent(state, TARGET_EDIT+m_typeIDStr);
+ }
+ });
+
+ return addLink;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public String getTypeIDStr() {
+ return m_typeIDStr;
+ }
+}
diff --git a/ccm-cms-types-decisiontree/web/themes/heirloom/contenttypes/DecisionTree.xsl b/ccm-cms-types-decisiontree/web/themes/heirloom/contenttypes/DecisionTree.xsl
new file mode 100644
index 000000000..4a1cf72e5
--- /dev/null
+++ b/ccm-cms-types-decisiontree/web/themes/heirloom/contenttypes/DecisionTree.xsl
@@ -0,0 +1,77 @@
+
+]>
+
+