From 22242c02a2ac0bbb63c3a3ae45f8229e36b8be84 Mon Sep 17 00:00:00 2001 From: jensp Date: Sun, 16 Oct 2011 10:50:39 +0000 Subject: [PATCH] =?UTF-8?q?Einf=C3=BChrung=20einer=20Assoziation=20zwische?= =?UTF-8?q?n=20GenericOrganizationalUnit=20Items.=20Die=20Assoziation=20ka?= =?UTF-8?q?nn=20nicht=20direkt=20verwendet=20werden,=20hierzu=20muss=20dur?= =?UTF-8?q?ch=20einen=20von=20GenericOrganizationalUnit=20abgeleiteten=20C?= =?UTF-8?q?ontent-Typ=20ein=20neuer=20AuthoringStep=20definiert=20werden?= =?UTF-8?q?=20und=20per=20AuthoringKitWizard#registerAssetStep(String,=20C?= =?UTF-8?q?lass,=20GlobalizedMessage,=20GlobalizedMessage,=20int)=20regist?= =?UTF-8?q?iert=20werden.=20Um=20das=20Erstellen=20eines=20solchen=20Autho?= =?UTF-8?q?ringSteps=20zu=20erleichtern=20werden=20anpassbare=20AddForms?= =?UTF-8?q?=20und=20Tables=20bereitsgestellt.=20F=C3=BCr=20Details=20siehe?= =?UTF-8?q?=20JavaDoc=20zu=20GenericOrganizationalUnit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Folgende Punkte sind noch zu beachten: - Version von ccm-cms auf 6.6.4 erhöht (wegen der Änderungen an GenericOrganizationalUnit.pdl) - ccm-sci-types-organization ist *nicht* mit diesen Änderungen kompatibel. Entsprechend in der application.xml von ccm-sci-types-organization eingetragen. git-svn-id: https://svn.libreccm.org/ccm/trunk@1169 8810af33-2d31-482b-a856-94f89814c4df --- ccm-cms/application.xml | 2 +- .../GenericOrganizationalUnit.pdl | 75 ++++ .../src/com/arsdigita/cms/ContentBundle.java | 3 +- .../GenericOrganizationalUnit.java | 156 ++++++-- ...ricOrganizationalUnitPersonCollection.java | 2 +- ...ganizationalUnitSubordinateCollection.java | 149 ++++++++ ...cOrganizationalUnitSuperiorCollection.java | 149 ++++++++ ...tSubordinateOrgaUnitAddFormCustomizer.java | 66 ++++ ...itSubordinateOrgaUnitsTableCustomizer.java | 80 +++++ ...UnitSuperiorOrgaUnitAddFormCustomizer.java | 59 +++ ...aUnitSuperiorOrgaUnitsTableCustomizer.java | 75 ++++ ...nericOrganizationalUnitContactAddForm.java | 4 +- ...ationalUnitSubordinateOrgaUnitAddForm.java | 115 ++++++ ...zationalUnitSubordinateOrgaUnitsTable.java | 340 ++++++++++++++++++ ...nizationalUnitSuperiorOrgaUnitAddForm.java | 113 ++++++ ...anizationalUnitSuperiorOrgaUnitsTable.java | 324 +++++++++++++++++ ccm-sci-types-organization/application.xml | 5 +- .../arsdigita/cms/contenttypes/SciProject.xml | 2 +- .../SciProjectListXmlGenerator.java | 12 + .../ui/SciDepartmentSubDepartmentAddForm.java | 3 +- .../ui/SciDepartmentSubDepartmentsTable.java | 1 - 21 files changed, 1691 insertions(+), 44 deletions(-) create mode 100644 ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnitSubordinateCollection.java create mode 100644 ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnitSuperiorCollection.java create mode 100644 ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitSubordinateOrgaUnitAddFormCustomizer.java create mode 100644 ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitSubordinateOrgaUnitsTableCustomizer.java create mode 100644 ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitSuperiorOrgaUnitAddFormCustomizer.java create mode 100644 ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitSuperiorOrgaUnitsTableCustomizer.java create mode 100644 ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitSubordinateOrgaUnitAddForm.java create mode 100644 ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitSubordinateOrgaUnitsTable.java create mode 100644 ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitSuperiorOrgaUnitAddForm.java create mode 100644 ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitSuperiorOrgaUnitsTable.java create mode 100644 ccm-sci-types-organization/src/com/arsdigita/cms/contenttypes/SciProjectListXmlGenerator.java diff --git a/ccm-cms/application.xml b/ccm-cms/application.xml index ad7962cd2..c95a8f4ea 100755 --- a/ccm-cms/application.xml +++ b/ccm-cms/application.xml @@ -2,7 +2,7 @@ diff --git a/ccm-cms/pdl/com/arsdigita/content-types/GenericOrganizationalUnit.pdl b/ccm-cms/pdl/com/arsdigita/content-types/GenericOrganizationalUnit.pdl index 0d4b1b325..0e8790e04 100644 --- a/ccm-cms/pdl/com/arsdigita/content-types/GenericOrganizationalUnit.pdl +++ b/ccm-cms/pdl/com/arsdigita/content-types/GenericOrganizationalUnit.pdl @@ -67,4 +67,79 @@ association { String[0..1] role_name = cms_organizationalunits_person_map.role_name VARCHAR(100); String[0..1] status = cms_organizationalunits_person_map.status VARCHAR(100); +} + +//Used build hierarchies of organizational units +association { + + GenericOrganizationalUnit[0..n] superiorOrgaunits = join cms_organizationalunits.organizationalunit_id + to cms_organizationalunits_hierarchy_map.subordinate_orgaunit_id, + join cms_organizationalunits_hierarchy_map.superior_orgaunit_id + to cms_organizationalunits.organizationalunit_id; + + GenericOrganizationalUnit[0..n] subordinateOrgaunits = join cms_organizationalunits.organizationalunit_id + to cms_organizationalunits_hierarchy_map.superior_orgaunit_id, + join cms_organizationalunits_hierarchy_map.subordinate_orgaunit_id + to cms_organizationalunits.organizationalunit_id; + + //Additonal attributes for the assoication + //Optional string for *internal* data + String[0..n] assocType = cms_organizationalunits_hierarchy_map.assoc_type VARCHAR(128); + //Integers for sorting + Integer[0..1] superiorOrgaUnitOrder = cms_organizationalunits_hierarchy_map.superior_orgaunit_order INTEGER; + Integer[0..1] subordinateOrgaUnitOrder = cms_organizationalunits_hierarchy_map.subordinate_orgaunit_order INTEGER; +} + +query getIdsOfSubordinateOrgaUnitsRecursivly{ + BigDecimal orgaunitId; + String orgaunitName; + + do { + with recursive subordinate_orgaunits(orgaunit_id, orgaunit_name) AS ( + select cms_organizationalunits.organizationalunit_id as orgaunit_id, + cms_items.name as orgaunit_name + from cms_organizationalunits + join cms_items on cms_organizationalunits.organizationalunit_id = cms_items.item_id + where cms_organizationalunits.organizationalunit_id = :orgaunitId + union all + select ou.organizationalunit_id as orgaunit_id, + cms_items.name as orgaunit_name + from subordinate_orgaunits sou, + cms_organizationalunits.organizationalunit_id + join cms_items on cms_organizationalunits.organizationalunit_id = cms_items.item_id + join cms_organizationalunits_hierarchy_map on ou.organizationalunit_id = cms_organizationalunits_hierarchy_map.subordinate_orgaunit_id + where cms_organizationalunits_hierarchy_map.superior_orgaunit_id = sou.orgaunit_id + ) + select orgaunit_id, orgaunit_name from subordinateOrgaUnits; + } map { + orgaunitId = subordinate_orgaunits.orgaunit_id; + orgaunitName = subordinate_orgaunits.orgaunit_name; + } +} + +query getIdsOfSubordinateOrgaUnitsRecursivlyWithAssocType{ + BigDecimal orgaunitId; + String orgaunitName; + + do { + with recursive subordinate_orgaunits(orgaunit_id, orgaunit_name) AS ( + select cms_organizationalunits.organizationalunit_id as orgaunit_id, + cms_items.name as orgaunit_name + from cms_organizationalunits + join cms_items on cms_organizationalunits.organizationalunit_id = cms_items.item_id + where cms_organizationalunits.organizationalunit_id = :orgaunitId + union all + select ou.organizationalunit_id as orgaunit_id, + cms_items.name as orgaunit_name + from subordinate_orgaunits sou, + cms_organizationalunits.organizationalunit_id + join cms_items on cms_organizationalunits.organizationalunit_id = cms_items.item_id + join cms_organizationalunits_hierarchy_map on ou.organizationalunit_id = cms_organizationalunits_hierarchy_map.subordinate_orgaunit_id + where cms_organizationalunits_hierarchy_map.superior_orgaunit_id = sou.orgaunit_id and cms_organizationalunits_hierarchy_map.assoc_type = :assocType + ) + select orgaunit_id, orgaunit_name from subordinateOrgaUnits; + } map { + orgaunitId = subordinate_orgaunits.orgaunit_id; + orgaunitName = subordinate_orgaunits.orgaunit_name; + } } \ No newline at end of file diff --git a/ccm-cms/src/com/arsdigita/cms/ContentBundle.java b/ccm-cms/src/com/arsdigita/cms/ContentBundle.java index 3f14e7e57..14ba7128f 100755 --- a/ccm-cms/src/com/arsdigita/cms/ContentBundle.java +++ b/ccm-cms/src/com/arsdigita/cms/ContentBundle.java @@ -327,8 +327,7 @@ public class ContentBundle extends ContentItem { instances.addEqualsFilter(LANGUAGE, language); if (instances.next()) { - contentItem = (ContentItem) DomainObjectFactory.newInstance(instances.getDataObject()); - ; + contentItem = (ContentItem) DomainObjectFactory.newInstance(instances.getDataObject()); } instances.close(); diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnit.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnit.java index ed3d7b796..af254e81f 100644 --- a/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnit.java +++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnit.java @@ -21,6 +21,9 @@ package com.arsdigita.cms.contenttypes; import com.arsdigita.cms.ContentBundle; import com.arsdigita.cms.ContentPage; +import com.arsdigita.cms.contenttypes.ui.GenericOrganizationalUnitSubordinateOrgaUnitAddForm; +import com.arsdigita.cms.contenttypes.ui.GenericOrganizationalUnitSubordinateOrgaUnitsTable; +import com.arsdigita.cms.ui.authoring.AuthoringKitWizard; import com.arsdigita.domain.DataObjectNotFoundException; import com.arsdigita.persistence.DataCollection; import com.arsdigita.persistence.DataObject; @@ -47,11 +50,9 @@ public class GenericOrganizationalUnit extends ContentPage { //public final static String ORGAUNIT_NAME = "ORGAUNIT_NAME"; public final static String ADDENDUM = "addendum"; public final static String CONTACTS = "contacts"; - public final static String CONTACT_TYPE = "contact_type"; - public final static String CONTACT_ORDER = "contact_order"; public final static String PERSONS = "persons"; - public final static String ROLE = "role_name"; - public final static String STATUS = "status"; + public final static String SUPERIOR_ORGAUNITS = "superiorOrgaunits"; + public final static String SUBORDINATE_ORGAUNITS = "subordinateOrgaunits"; public final static String BASE_DATA_OBJECT_TYPE = "com.arsdigita.cms.contenttypes.GenericOrganizationalUnit"; @@ -59,21 +60,21 @@ public class GenericOrganizationalUnit extends ContentPage { this(BASE_DATA_OBJECT_TYPE); } - public GenericOrganizationalUnit(BigDecimal id) + public GenericOrganizationalUnit(final BigDecimal id) throws DataObjectNotFoundException { this(new OID(BASE_DATA_OBJECT_TYPE, id)); } - public GenericOrganizationalUnit(OID oid) + public GenericOrganizationalUnit(final OID oid) throws DataObjectNotFoundException { super(oid); } - public GenericOrganizationalUnit(DataObject obj) { + public GenericOrganizationalUnit(final DataObject obj) { super(obj); } - public GenericOrganizationalUnit(String type) { + public GenericOrganizationalUnit(final String type) { super(type); } @@ -81,7 +82,7 @@ public class GenericOrganizationalUnit extends ContentPage { return (String) get(ADDENDUM); } - public void setAddendum(String addendum) { + public void setAddendum(final String addendum) { set(ADDENDUM, addendum); } @@ -90,19 +91,22 @@ public class GenericOrganizationalUnit extends ContentPage { CONTACTS)); } - public void addContact(GenericContact contact, String contactType) { + public void addContact(final GenericContact contact, + final String contactType) { Assert.exists(contact, GenericContact.class); logger.debug(String.format("Adding contact of type \"%s\"...", contactType)); - DataObject link = add(CONTACTS, contact); + final DataObject link = add(CONTACTS, contact); - link.set(CONTACT_TYPE, contactType); - link.set(CONTACT_ORDER, Integer.valueOf((int) getContacts().size())); + link.set(GenericOrganizationalUnitContactCollection.CONTACT_TYPE, + contactType); + link.set(GenericOrganizationalUnitContactCollection.CONTACT_ORDER, + Integer.valueOf((int) getContacts().size())); link.save(); } - public void removeContact(GenericContact contact) { + public void removeContact(final GenericContact contact) { Assert.exists(contact, GenericContact.class); remove(CONTACTS, contact); } @@ -113,37 +117,125 @@ public class GenericOrganizationalUnit extends ContentPage { public GenericOrganizationalUnitPersonCollection getPersons() { DataCollection dataColl = (DataCollection) get(PERSONS); - logger.debug(String.format("GenericOrganizationalUnitPersonCollection size = %d", dataColl.size())); + logger.debug(String.format( + "GenericOrganizationalUnitPersonCollection size = %d", dataColl. + size())); return new GenericOrganizationalUnitPersonCollection(dataColl); } - public void addPerson(GenericPerson person, String role, String status) { + public void addPerson(final GenericPerson person, + final String role, + final String status) { Assert.exists(person, GenericPerson.class); GenericPerson personToLink = person; - - ContentBundle bundle = person.getContentBundle(); - if ((bundle != null) && (bundle.hasInstance(this.getLanguage()))) { - personToLink = (GenericPerson) bundle.getInstance(this.getLanguage()); - } - - Assert.exists(personToLink, GenericPerson.class); - - DataObject link = add(PERSONS, personToLink); - link.set(ROLE, role); - link.set(STATUS, status); - link.save(); + final ContentBundle bundle = person.getContentBundle(); + if ((bundle != null) && (bundle.hasInstance(this.getLanguage()))) { + personToLink = + (GenericPerson) bundle.getInstance(this.getLanguage()); + } + + Assert.exists(personToLink, GenericPerson.class); + + final DataObject link = add(PERSONS, personToLink); + + link.set(GenericOrganizationalUnitPersonCollection.PERSON_ROLE, role); + link.set(GenericOrganizationalUnitPersonCollection.STATUS, status); + link.save(); } - public void removePerson(GenericPerson person) { + public void removePerson(final GenericPerson person) { logger.debug("Removing person association..."); - Assert.exists(person, GenericPerson.class); - remove(PERSONS, person); + Assert.exists(person, GenericPerson.class); + remove(PERSONS, person); } public boolean hasPersons() { return !this.getPersons().isEmpty(); } - + + public GenericOrganizationalUnitSuperiorCollection getSuperiorOrgaUnits() { + final DataCollection dataCollection = (DataCollection) get( + SUPERIOR_ORGAUNITS); + return new GenericOrganizationalUnitSuperiorCollection(dataCollection); + } + + public void addSuperiorOrgaUnit(final GenericOrganizationalUnit orgaunit, + final String assocType) { + Assert.exists(orgaunit, GenericOrganizationalUnit.class); + + final DataObject link = add(SUPERIOR_ORGAUNITS, orgaunit); + link.set(GenericOrganizationalUnitSuperiorCollection.ASSOCTYPE, + assocType); + link.set( + GenericOrganizationalUnitSuperiorCollection.SUPERIOR_ORGAUNIT_ORDER, + getSuperiorOrgaUnits().size()); + link.save(); + } + + public void addSuperiorOrgaUnit(final GenericOrganizationalUnit orgaunit) { + addSuperiorOrgaUnit(orgaunit, ""); + } + + public void removeSuperiorOrgaUnit( + final GenericOrganizationalUnit orgaunit) { + Assert.exists(orgaunit, GenericOrganizationalUnit.class); + remove(SUPERIOR_ORGAUNITS, orgaunit); + } + + public boolean hasSuperiorOrgaUnits() { + return !getSuperiorOrgaUnits().isEmpty(); + } + + /** + * Gets a collection of subordinate organizational units. Note that their + * is no authoring step registered for this property. The {@code ccm-cms} + * module provides only a form for adding subordinate organizational units + * and a table for showing them. Subtypes of + * {@code GenericOrganizationalUnit} may add these components to their + * authoring steps via a new authoring step which contains the form + * and the table. These authoring steps should be registered by using + * {@link AuthoringKitWizard#registerAssetStep(java.lang.String, java.lang.Class, com.arsdigita.globalization.GlobalizedMessage, com.arsdigita.globalization.GlobalizedMessage, int) } + * in the initalizer of the content type. Some aspects of the form and + * table, for example the labels, can be configured using implementations + * of two interfaces. Please refer to the documentation of + * {@link GenericOrganizationalUnitSubordinateOrgaUnitsTable} and + * {@link GenericOrganizationalUnitSubordinateOrgaUnitAddForm} + * for more information about customizing the table and the form. + * + * @return A collection of subordinate organizational units. + */ + public GenericOrganizationalUnitSubordinateCollection getSubordinateOrgaUnits() { + final DataCollection dataCollection = (DataCollection) get( + SUBORDINATE_ORGAUNITS); + return new GenericOrganizationalUnitSubordinateCollection(dataCollection); + } + + public void addSubordinateOrgaUnit(final GenericOrganizationalUnit orgaunit, + final String assocType) { + Assert.exists(orgaunit, GenericOrganizationalUnit.class); + + final DataObject link = add(SUBORDINATE_ORGAUNITS, orgaunit); + link.set(GenericOrganizationalUnitSubordinateCollection.ASSOCTYPE, + assocType); + link.set( + GenericOrganizationalUnitSubordinateCollection.SUBORDINATE_ORGAUNIT_ORDER, + getSubordinateOrgaUnits().size()); + link.save(); + } + + public void addSubordinateOrgaUnit(final GenericOrganizationalUnit orgaunit) { + addSubordinateOrgaUnit(orgaunit, ""); + } + + public void removeSubordinateOrgaUnit( + final GenericOrganizationalUnit orgaunit) { + Assert.exists(orgaunit, GenericOrganizationalUnit.class); + remove(SUBORDINATE_ORGAUNITS, orgaunit); + } + + public boolean hasSubordinateOrgaUnits() { + return !getSubordinateOrgaUnits().isEmpty(); + } } diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnitPersonCollection.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnitPersonCollection.java index b1e179c24..e31ddb414 100644 --- a/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnitPersonCollection.java +++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnitPersonCollection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Jens Pelzetter, for the Center of Social Politics of the University of Bremen + * Copyright (c) 2010 Jens Pelzetter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnitSubordinateCollection.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnitSubordinateCollection.java new file mode 100644 index 000000000..fa11d3ec6 --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnitSubordinateCollection.java @@ -0,0 +1,149 @@ +package com.arsdigita.cms.contenttypes; + +import com.arsdigita.cms.ContentItem; +import com.arsdigita.cms.ContentPage; +import com.arsdigita.domain.DomainCollection; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.persistence.DataCollection; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.OID; + +/** + * + * @author Jens Pelzetter + * @version $Id$ + */ +public class GenericOrganizationalUnitSubordinateCollection extends DomainCollection { + + public static final String ASSOCTYPE = "assocType"; + public static final String SUBORDINATE_ORGAUNIT_ORDER = + "subordinateOrgaUnitOrder"; + public static final String LINK_ASSOCTYPE = "link." + ASSOCTYPE; + public static final String LINK_SUBORDINATE_ORGAUNIT_ORDER = + "link." + SUBORDINATE_ORGAUNIT_ORDER; + + public GenericOrganizationalUnitSubordinateCollection( + final DataCollection dataCollection) { + super(dataCollection); + m_dataCollection.addOrder(SUBORDINATE_ORGAUNIT_ORDER + " asc"); + } + + public String getAssocType() { + return (String) m_dataCollection.get(LINK_ASSOCTYPE); + } + + public void setAssocType(final String assocType) { + final DataObject link = (DataObject) get("link"); + link.set(ASSOCTYPE, assocType); + } + + public Integer getSubordinateOrder() { + return (Integer) m_dataCollection.get(LINK_SUBORDINATE_ORGAUNIT_ORDER); + } + + public void setSubordinateOrder(final Integer order) { + final DataObject link = (DataObject) get("link"); + link.set(SUBORDINATE_ORGAUNIT_ORDER, order); + } + + public void swapWithNext(final GenericOrganizationalUnit orgaunit) { + if (orgaunit == null) { + throw new IllegalArgumentException( + "Parameter orgaunit is null. Can't swap position with null"); + } + + int currentPos = 0; + int currentIndex = 0; + int nextIndex = 0; + + rewind(); + while (next()) { + currentPos = getPosition(); + currentIndex = getSubordinateOrder(); + if (orgaunit.equals(getGenericOrganizationalUnit())) { + break; + } + } + + if (next()) { + nextIndex = getSubordinateOrder(); + } else { + throw new IllegalArgumentException("The provided organizational " + + "unit is the last one in the collection, so there is no " + + "next object to swap with."); + } + + rewind(); + + while (this.getPosition() != currentPos) { + next(); + } + + setSubordinateOrder(nextIndex); + next(); + setSubordinateOrder(currentIndex); + rewind(); + } + + public void swapWithPrevious(final GenericOrganizationalUnit orgaunit) { + if (orgaunit == null) { + throw new IllegalArgumentException( + "Parameter orgaunit is null. Can't swap position with null"); + } + + int previousPos = 0; + int previousIndex = 0; + int currentPos = 0; + int currentIndex = 0; + + rewind(); + while (next()) { + currentPos = getPosition(); + currentIndex = getSubordinateOrder(); + + if (orgaunit.equals(getGenericOrganizationalUnit())) { + break; + } + + previousPos = currentPos; + previousIndex = currentIndex; + } + + if (currentPos == 0) { + throw new IllegalArgumentException("The provided contact is the " + + "first one in this collection, so there is no previous " + + "one to switch with."); + } + + rewind(); + while (getPosition() != previousPos) { + this.next(); + } + + setSubordinateOrder(currentIndex); + next(); + setSubordinateOrder(previousIndex); + rewind(); + } + + public GenericOrganizationalUnit getGenericOrganizationalUnit() { + return (GenericOrganizationalUnit) DomainObjectFactory.newInstance(m_dataCollection. + getDataObject()); + } + + public OID getOID() { + return m_dataCollection.getDataObject().getOID(); + } + + public String getName() { + return (String) m_dataCollection.get(ContentItem.NAME); + } + + public String getTitle() { + return (String) m_dataCollection.get(ContentPage.TITLE); + } + + public String getAddendum() { + return (String) m_dataCollection.get(GenericOrganizationalUnit.ADDENDUM); + } +} diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnitSuperiorCollection.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnitSuperiorCollection.java new file mode 100644 index 000000000..5f8afde79 --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/GenericOrganizationalUnitSuperiorCollection.java @@ -0,0 +1,149 @@ +package com.arsdigita.cms.contenttypes; + +import com.arsdigita.cms.ContentItem; +import com.arsdigita.cms.ContentPage; +import com.arsdigita.domain.DomainCollection; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.persistence.DataCollection; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.OID; + +/** + * + * @author Jens Pelzetter + * @version $Id$ + */ +public class GenericOrganizationalUnitSuperiorCollection extends DomainCollection { + + public static final String ASSOCTYPE = "assocType"; + public static final String SUPERIOR_ORGAUNIT_ORDER = + "superiorOrgaUnitOrder"; + public static final String LINK_ASSOCTYPE = "link." + ASSOCTYPE; + public static final String LINK_SUPERIOR_ORGAUNIT_ORDER = + "link." + SUPERIOR_ORGAUNIT_ORDER; + + public GenericOrganizationalUnitSuperiorCollection( + final DataCollection dataCollection) { + super(dataCollection); + m_dataCollection.addOrder(SUPERIOR_ORGAUNIT_ORDER + " asc"); + } + + public String getAssocType() { + return (String) m_dataCollection.get(LINK_ASSOCTYPE); + } + + public void setAssocType(final String assocType) { + final DataObject link = (DataObject) get("link"); + link.set(ASSOCTYPE, assocType); + } + + public Integer getSuperiorOrder() { + return (Integer) m_dataCollection.get(LINK_SUPERIOR_ORGAUNIT_ORDER); + } + + public void setSuperiorOrder(final Integer order) { + final DataObject link = (DataObject) get("link"); + link.set(SUPERIOR_ORGAUNIT_ORDER, order); + } + + public void swapWithNext(final GenericOrganizationalUnit orgaunit) { + if (orgaunit == null) { + throw new IllegalArgumentException( + "Parameter orgaunit is null. Can't swap position with null"); + } + + int currentPos = 0; + int currentIndex = 0; + int nextIndex = 0; + + rewind(); + while (next()) { + currentPos = getPosition(); + currentIndex = getSuperiorOrder(); + if (orgaunit.equals(getGenericOrganizationalUnit())) { + break; + } + } + + if (next()) { + nextIndex = getSuperiorOrder(); + } else { + throw new IllegalArgumentException("The provided organizational " + + "unit is the last one in the collection, so there is no " + + "next object to swap with."); + } + + rewind(); + + while (this.getPosition() != currentPos) { + next(); + } + + setSuperiorOrder(nextIndex); + next(); + setSuperiorOrder(currentIndex); + rewind(); + } + + public void swapWithPrevious(final GenericOrganizationalUnit orgaunit) { + if (orgaunit == null) { + throw new IllegalArgumentException( + "Parameter orgaunit is null. Can't swap position with null"); + } + + int previousPos = 0; + int previousIndex = 0; + int currentPos = 0; + int currentIndex = 0; + + rewind(); + while (next()) { + currentPos = getPosition(); + currentIndex = getSuperiorOrder(); + + if (orgaunit.equals(getGenericOrganizationalUnit())) { + break; + } + + previousPos = currentPos; + previousIndex = currentIndex; + } + + if (currentPos == 0) { + throw new IllegalArgumentException("The provided contact is the " + + "first one in this collection, so there is no previous " + + "one to switch with."); + } + + rewind(); + while (getPosition() != previousPos) { + this.next(); + } + + setSuperiorOrder(currentIndex); + next(); + setSuperiorOrder(previousIndex); + rewind(); + } + + public GenericOrganizationalUnit getGenericOrganizationalUnit() { + return (GenericOrganizationalUnit) DomainObjectFactory.newInstance(m_dataCollection. + getDataObject()); + } + + public OID getOID() { + return m_dataCollection.getDataObject().getOID(); + } + + public String getName() { + return (String) m_dataCollection.get(ContentItem.NAME); + } + + public String getTitle() { + return (String) m_dataCollection.get(ContentPage.TITLE); + } + + public String getAddendum() { + return (String) m_dataCollection.get(GenericOrganizationalUnit.ADDENDUM); + } +} diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitSubordinateOrgaUnitAddFormCustomizer.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitSubordinateOrgaUnitAddFormCustomizer.java new file mode 100644 index 000000000..c491f5811 --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitSubordinateOrgaUnitAddFormCustomizer.java @@ -0,0 +1,66 @@ +package com.arsdigita.cms.contenttypes.ui; + +/** + * Implementations of this class are used to customize an instance of + * {@link GenericOrganizationalUnitSubordinateOrgaUnitAddForm}. Methods ending + * with {@code Label} or {@code Message}, for example + * {@link #getEmptyViewLabel()} are supposed + * to return the localized content of a label component. This means + * that implementations of such methods will delegate to some globalization + * utility. + * + * @author Jens Pelzetter + * @version $Id$ + */ +public interface GenericOrgaUnitSubordinateOrgaUnitAddFormCustomizer { + + /** + * + * @return Label for the item search widget of the add from. + */ + String getSelectSubordinateOrgaUnitLabel(); + + /** + * + * @return Can be used to limit the content items shown by the item search + * widget to a specific type. + */ + String getSubordinateOrgaUnitType(); + + /** + * + * @return The value for the {@code assocType} field. When adding a + * new subordinate organizational unit, the {@code assocType} field of + * the new association will be set the value returned by this method. + */ + String getAssocType(); + + /** + * + * @return Message to show if the save button has been hit without selecting + * an item. + */ + String getNothingSelectedMessage(); + + /** + * + * @return Message to show if the selected item has no suitable language + * variant. + */ + String getNoSuitableLanguageVariantMessage(); + + /** + * + * @return Message to show if the selected item is the same as the current + * item. + */ + String getAddingToItselfMessage(); + + /** + * + * @return Message to show if the selected item has already been added + * as a subordinate organizational unit. + */ + String getAlreadyAddedMessage(); + +} diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitSubordinateOrgaUnitsTableCustomizer.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitSubordinateOrgaUnitsTableCustomizer.java new file mode 100644 index 000000000..d3456dcd9 --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitSubordinateOrgaUnitsTableCustomizer.java @@ -0,0 +1,80 @@ +package com.arsdigita.cms.contenttypes.ui; + +/** + * Implementations of this class are used to customize an instance of + * {@link GenericOrganizationalUnitSubordinateOrgaUnitTable}. Methods ending + * with {@code Label}, for example {@link #getEmptyViewLabel()} are supposed + * to return the localized content of a label component. This means + * that implementations of such methods will delegate to some globalization + * utility. + * + * @author Jens Pelzetter + * @version $Id$ + */ +public interface GenericOrgaUnitSubordinateOrgaUnitsTableCustomizer { + + /** + * @return The label used instead of an empty table. + */ + String getEmptyViewLabel(); + + /** + * + * @return Label for the column heading of the first column which shows + * the titles of the subordinate organizational units. + */ + String getNameColumnLabel(); + + /** + * @return The column heading for the second column which displays delete + * links for the associations. + */ + String getDeleteColumnLabel(); + + /** + * + * @return Column heading for the column containing the {@code Up} links + * for sorting the subordinate organizational units. + */ + String getUpColumnLabel(); + + /** + * + * @return Column heading for the column containing the {@code Down} links + * for sorting the subordinate organizational units. + */ + String getDownColumnLabel(); + + /** + * + * @return Label for the delete links. + */ + String getDeleteLabel(); + + /** + * + * @return Label for the up links + */ + String getUpLabel(); + + /** + * + * @return Label for the down links + */ + String getDownLabel(); + + /** + * + * @return Text for the confirmation message when deleting an association. + */ + String getConfirmRemoveLabel(); + + /** + * + * @return The value of the {@code assocType} property of the association + * to filter for. If this method returns something different from null + * or the empty string, the collection of subordinate organizational units + * is filtered using the return value. + */ + String getAssocType(); +} diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitSuperiorOrgaUnitAddFormCustomizer.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitSuperiorOrgaUnitAddFormCustomizer.java new file mode 100644 index 000000000..ccdcfc892 --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitSuperiorOrgaUnitAddFormCustomizer.java @@ -0,0 +1,59 @@ +package com.arsdigita.cms.contenttypes.ui; + +/** + * + * @author Jens Pelzetter + * @version $Id$ + */ +public interface GenericOrgaUnitSuperiorOrgaUnitAddFormCustomizer { + + /** + * + * @return Label for the item search widget of the add from. + */ + String getSelectSuperiorOrgaUnitLabel(); + + /** + * + * @return Can be used to limit the content items shown by the item search + * widget to a specific type. + */ + String getSuperiorOrgaUnitType(); + + /** + * + * @return The value for the {@code assocType} field. When adding a + * new superior organizational unit, the {@code assocType} field of + * the new association will be set the value returned by this method. + */ + String getAssocType(); + + /** + * + * @return Message to show if the save button has been hit without selecting + * an item. + */ + String getNothingSelectedMessage(); + + /** + * + * @return Message to show if the selected item has no suitable language + * variant. + */ + String getNoSuitableLanguageVariantMessage(); + + /** + * + * @return Message to show if the selected item is the same as the current + * item. + */ + String getAddingToItselfMessage(); + + /** + * + * @return Message to show if the selected item has already been added + * as a superior organizational unit. + */ + String getAlreadyAddedMessage(); + +} diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitSuperiorOrgaUnitsTableCustomizer.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitSuperiorOrgaUnitsTableCustomizer.java new file mode 100644 index 000000000..6286bb827 --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrgaUnitSuperiorOrgaUnitsTableCustomizer.java @@ -0,0 +1,75 @@ +package com.arsdigita.cms.contenttypes.ui; + +/** + * + * @author Jens Pelzetter + * @version $Id$ + */ +public interface GenericOrgaUnitSuperiorOrgaUnitsTableCustomizer { + + /** + * @return The label used instead of an empty table. + */ + String getEmptyViewLabel(); + + /** + * + * @return Label for the column heading of the first column which shows + * the titles of the superior organizational units. + */ + String getNameColumnLabel(); + + /** + * @return The column heading for the second column which displays delete + * links for the associations. + */ + String getDeleteColumnLabel(); + + /** + * + * @return Column heading for the column containing the {@code Up} links + * for sorting the superior organizational units. + */ + String getUpColumnLabel(); + + /** + * + * @return Column heading for the column containing the {@code Down} links + * for sorting the superior organizational units. + */ + String getDownColumnLabel(); + + /** + * + * @return Label for the delete links. + */ + String getDeleteLabel(); + + /** + * + * @return Label for the up links + */ + String getUpLabel(); + + /** + * + * @return Label for the down links + */ + String getDownLabel(); + + /** + * + * @return Text for the confirmation message when deleting an association. + */ + String getConfirmRemoveLabel(); + + /** + * + * @return The value of the {@code assocType} property of the association + * to filter for. If this method returns something different from null + * or the empty string, the collection of superior organizational units + * is filtered using the return value. + */ + String getAssocType(); + +} diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitContactAddForm.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitContactAddForm.java index e61d5958d..8044cb000 100644 --- a/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitContactAddForm.java +++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitContactAddForm.java @@ -85,7 +85,7 @@ public class GenericOrganizationalUnitContactAddForm add(new Label(ContenttypesGlobalizationUtil.globalize( "cms.contenttypes.ui.genericorgaunit.contact.type"))); ParameterModel contactTypeParam = new StringParameter( - GenericOrganizationalUnit.CONTACT_TYPE); + GenericOrganizationalUnitContactCollection.CONTACT_TYPE); SingleSelect contactType = new SingleSelect(contactTypeParam); contactType.addValidationListener(new NotNullValidationListener()); contactType.addOption(new Option("", @@ -148,7 +148,7 @@ public class GenericOrganizationalUnitContactAddForm orgaunit.addContact(contact, (String) data.get( - GenericOrganizationalUnit.CONTACT_TYPE)); + GenericOrganizationalUnitContactCollection.CONTACT_TYPE)); } else { GenericOrganizationalUnitContactCollection contacts; diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitSubordinateOrgaUnitAddForm.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitSubordinateOrgaUnitAddForm.java new file mode 100644 index 000000000..a1c2a9a75 --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitSubordinateOrgaUnitAddForm.java @@ -0,0 +1,115 @@ +package com.arsdigita.cms.contenttypes.ui; + +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.FormProcessException; +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.cms.ContentType; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.contenttypes.GenericOrganizationalUnit; +import com.arsdigita.cms.contenttypes.GenericOrganizationalUnitSubordinateCollection; +import com.arsdigita.cms.ui.ItemSearchWidget; +import com.arsdigita.cms.ui.authoring.BasicItemForm; + +/** + * Form for adding a subordinate organizational unit to a organizational unit. + * Can be customized using {@link GenericOrgaUnitSubordinateOrgaUnitAddFormCustomizer}. + * + * @author Jens Pelzetter + * @version $Id$ + */ +public class GenericOrganizationalUnitSubordinateOrgaUnitAddForm + extends BasicItemForm + implements FormProcessListener, + FormInitListener { + + private ItemSearchWidget itemSearch; + private final String ITEM_SEARCH = "subordinateOrgaUnits"; + private final GenericOrgaUnitSubordinateOrgaUnitAddFormCustomizer customizer; + + public GenericOrganizationalUnitSubordinateOrgaUnitAddForm( + final ItemSelectionModel itemModel, + final GenericOrgaUnitSubordinateOrgaUnitAddFormCustomizer customizer) { + super("SubordinateOrgaUnitsAddForm", itemModel); + this.customizer = customizer; + } + + @Override + protected void addWidgets() { + add(new Label(customizer.getSelectSubordinateOrgaUnitLabel())); + itemSearch = new ItemSearchWidget( + ITEM_SEARCH, + ContentType.findByAssociatedObjectType( + customizer.getSubordinateOrgaUnitType())); + add(itemSearch); + } + + @Override + public void init(final FormSectionEvent fse) throws FormProcessException { + final PageState state = fse.getPageState(); + + setVisible(state, true); + } + + @Override + public void process(final FormSectionEvent fse) throws FormProcessException { + final FormData data = fse.getFormData(); + final PageState state = fse.getPageState(); + final GenericOrganizationalUnit orgaunit = + (GenericOrganizationalUnit) getItemSelectionModel(). + getSelectedObject(state); + + if (getSaveCancelSection().getSaveButton().isSelected(state)) { + GenericOrganizationalUnit subOrgaUnit = + (GenericOrganizationalUnit) data.get( + ITEM_SEARCH); + subOrgaUnit = (GenericOrganizationalUnit) subOrgaUnit. + getContentBundle().getInstance(orgaunit.getLanguage(), true); + + orgaunit.addSubordinateOrgaUnit(subOrgaUnit, customizer.getAssocType()); + } + + init(fse); + } + + @Override + public void validate(final FormSectionEvent fse) + throws FormProcessException { + final PageState state = fse.getPageState(); + final FormData data = fse.getFormData(); + + if (data.get(ITEM_SEARCH) == null) { + data.addError(customizer.getNothingSelectedMessage()); + return; + } + + final GenericOrganizationalUnit orgaunit = + (GenericOrganizationalUnit) getItemSelectionModel(). + getSelectedObject(state); + GenericOrganizationalUnit subOrgaUnit = + (GenericOrganizationalUnit) data.get( + ITEM_SEARCH); + if (!(subOrgaUnit.getContentBundle().hasInstance(orgaunit.getLanguage(), + true))) { + data.addError(customizer.getNoSuitableLanguageVariantMessage()); + return; + } + + subOrgaUnit = (GenericOrganizationalUnit) subOrgaUnit.getContentBundle().getInstance(orgaunit.getLanguage(), true); + + if (orgaunit.getID().equals(subOrgaUnit.getID())) { + data.addError(customizer.getAddingToItselfMessage()); + return; + } + + final GenericOrganizationalUnitSubordinateCollection subOrgaUnits = orgaunit.getSubordinateOrgaUnits(); + subOrgaUnits.addFilter(String.format("id = %s", subOrgaUnit.getID().toString())); + if (subOrgaUnits.size() > 0) { + data.addError(customizer.getAlreadyAddedMessage()); + } + subOrgaUnits.close(); + } +} diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitSubordinateOrgaUnitsTable.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitSubordinateOrgaUnitsTable.java new file mode 100644 index 000000000..b514b5ce3 --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitSubordinateOrgaUnitsTable.java @@ -0,0 +1,340 @@ +package com.arsdigita.cms.contenttypes.ui; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +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.CMS; +import com.arsdigita.cms.ContentSection; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.contenttypes.GenericOrganizationalUnit; +import com.arsdigita.cms.contenttypes.GenericOrganizationalUnitSubordinateCollection; +import com.arsdigita.cms.dispatcher.ItemResolver; +import com.arsdigita.cms.dispatcher.Utilities; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.persistence.OID; +import com.arsdigita.util.LockableImpl; +import org.apache.log4j.Logger; + +/** + * Table for showing subordinate organizational units. Several aspects can + * be customized using an implementation of + * {@link GenericOrgaUnitSubordinateOrgaUnitsTableCustomizer}. An implementation + * of {@link GenericOrgaUnitSubordinateOrgaUnitsTableCustomizer} has to be + * passed to the constructor of this table by the authoring step containing + * the table. + * + * @author Jens Pelzetter + * @version $Id$ + */ +public abstract class GenericOrganizationalUnitSubordinateOrgaUnitsTable + extends Table { + + private final Logger logger = + Logger.getLogger( + GenericOrganizationalUnitSubordinateOrgaUnitsTable.class); + private final String TABLE_COL_EDIT = "table_col_edit"; + private final String TABLE_COL_DEL = "table_col_del"; + private final String TABLE_COL_UP = "table_col_up"; + private final String TABLE_COL_DOWN = "table_col_down"; + private final ItemSelectionModel itemModel; + private final GenericOrgaUnitSubordinateOrgaUnitsTableCustomizer customizer; + + public GenericOrganizationalUnitSubordinateOrgaUnitsTable( + final ItemSelectionModel itemModel, + final GenericOrgaUnitSubordinateOrgaUnitsTableCustomizer customizer) { + super(); + this.itemModel = itemModel; + this.customizer = customizer; + + setEmptyView(new Label(customizer.getEmptyViewLabel())); + + final TableColumnModel columnModel = getColumnModel(); + columnModel.add(new TableColumn(0, + customizer.getNameColumnLabel(), + TABLE_COL_EDIT)); + columnModel.add(new TableColumn(1, + customizer.getDeleteColumnLabel(), + TABLE_COL_DEL)); + columnModel.add(new TableColumn(2, + customizer.getUpColumnLabel(), + TABLE_COL_UP)); + columnModel.add(new TableColumn(3, + customizer.getDownColumnLabel(), + TABLE_COL_DOWN)); + + setModelBuilder(new ModelBuilder(itemModel, customizer)); + + columnModel.get(0).setCellRenderer(new EditCellRenderer()); + columnModel.get(1).setCellRenderer(new DeleteCellRenderer()); + columnModel.get(2).setCellRenderer(new UpCellRenderer()); + columnModel.get(3).setCellRenderer(new DownCellRenderer()); + + addTableActionListener(new ActionListener()); + } + + private class ModelBuilder extends LockableImpl implements TableModelBuilder { + + private final ItemSelectionModel itemModel; + private final GenericOrgaUnitSubordinateOrgaUnitsTableCustomizer customizer; + + public ModelBuilder( + final ItemSelectionModel itemModel, + final GenericOrgaUnitSubordinateOrgaUnitsTableCustomizer customizer) { + this.itemModel = itemModel; + this.customizer = customizer; + } + + @Override + public TableModel makeModel(final Table table, final PageState state) { + table.getRowSelectionModel().clearSelection(state); + final GenericOrganizationalUnit orgaunit = + (GenericOrganizationalUnit) itemModel. + getSelectedObject(state); + return new Model(table, state, orgaunit, customizer); + } + } + + private class Model implements TableModel { + + private final Table table; + private final GenericOrganizationalUnitSubordinateCollection subordinateOrgaUnits; + private final GenericOrgaUnitSubordinateOrgaUnitsTableCustomizer customizer; + + public Model(final Table table, + final PageState state, + final GenericOrganizationalUnit orgaunit, + final GenericOrgaUnitSubordinateOrgaUnitsTableCustomizer customizer) { + this.table = table; + subordinateOrgaUnits = orgaunit.getSubordinateOrgaUnits(); + if ((customizer.getAssocType() != null) + && !(customizer.getAssocType().isEmpty())) { + subordinateOrgaUnits.addFilter(String.format("assocType = '%s", + customizer. + getAssocType())); + } + this.customizer = customizer; + } + + @Override + public int getColumnCount() { + return table.getColumnModel().size(); + } + + @Override + public boolean nextRow() { + boolean ret; + + if ((subordinateOrgaUnits != null) && subordinateOrgaUnits.next()) { + ret = true; + } else { + ret = false; + } + + return ret; + } + + @Override + public Object getElementAt(final int columnIndex) { + switch (columnIndex) { + case 0: + return subordinateOrgaUnits.getTitle(); + case 1: + return customizer.getDeleteLabel(); + case 2: + return customizer.getUpLabel(); + case 3: + return customizer.getDownLabel(); + default: + return null; + } + } + + @Override + public Object getKeyAt(final int columnIndex) { + return subordinateOrgaUnits.getOID(); + } + } + + private class EditCellRenderer + extends LockableImpl + implements TableCellRenderer { + + @Override + public Component getComponent(final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int column) { + final com.arsdigita.cms.SecurityManager securityManager = Utilities. + getSecurityManager(state); + final GenericOrganizationalUnit subordinateOrgaUnit = + (GenericOrganizationalUnit) DomainObjectFactory. + newInstance((OID) key); + + final boolean canEdit = securityManager.canAccess( + state.getRequest(), + com.arsdigita.cms.SecurityManager.EDIT_ITEM, + subordinateOrgaUnit); + + if (canEdit) { + final ContentSection section = CMS.getContext(). + getContentSection(); + final ItemResolver resolver = section.getItemResolver(); + final Link link = + new Link( + String.format("%s (%s)", + value.toString(), + subordinateOrgaUnit.getLanguage()), + resolver.generateItemURL(state, + subordinateOrgaUnit, + section, + subordinateOrgaUnit.getVersion())); + + return link; + } else { + final Label label = new Label(String.format( + "%s (%s)", + value.toString(), + subordinateOrgaUnit.getLanguage())); + return label; + } + } + } + + private class DeleteCellRenderer + extends LockableImpl + implements TableCellRenderer { + + @Override + public Component getComponent(final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int column) { + final com.arsdigita.cms.SecurityManager securityManager = Utilities. + getSecurityManager(state); + final GenericOrganizationalUnit orgaunit = + (GenericOrganizationalUnit) itemModel. + getSelectedObject(state); + + + boolean canEdit = securityManager.canAccess( + state.getRequest(), + com.arsdigita.cms.SecurityManager.EDIT_ITEM, + orgaunit); + + if (canEdit) { + final ControlLink link = new ControlLink(value.toString()); + link.setConfirmation(customizer.getConfirmRemoveLabel()); + return link; + } else { + final Label label = new Label(""); + return label; + } + } + } + + private class UpCellRenderer + extends LockableImpl + implements TableCellRenderer { + + public Component getComponent(final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int column) { + + if (row == 0) { + final Label label = new Label(""); + return label; + } else { + final ControlLink link = + new ControlLink(customizer.getUpLabel()); + return link; + } + } + } + + private class DownCellRenderer + extends LockableImpl + implements TableCellRenderer { + + @Override + public Component getComponent(final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int column) { + + final GenericOrganizationalUnit orgaunit = + (GenericOrganizationalUnit) itemModel. + getSelectedObject(state); + final GenericOrganizationalUnitSubordinateCollection subOrgaUnits = + orgaunit. + getSubordinateOrgaUnits(); + + if ((subOrgaUnits.size() - 1) == row) { + final Label label = new Label(""); + return label; + } else { + final ControlLink link = + new ControlLink(customizer.getDownLabel()); + return link; + } + } + } + + private class ActionListener implements TableActionListener { + + @Override + public void cellSelected(final TableActionEvent event) { + final PageState state = event.getPageState(); + + final GenericOrganizationalUnit orgaunit = + (GenericOrganizationalUnit) itemModel. + getSelectedObject( + state); + final GenericOrganizationalUnit subOrgaUnit = + (GenericOrganizationalUnit) DomainObjectFactory. + newInstance((OID) event.getRowKey()); + final GenericOrganizationalUnitSubordinateCollection subOrgaUnits = + orgaunit. + getSubordinateOrgaUnits(); + + final TableColumn column = getColumnModel().get(event.getColumn(). + intValue()); + final String headerKey = column.getHeaderKey().toString(); + if (TABLE_COL_EDIT.equals(headerKey)) { + //Nothing now + } else if (TABLE_COL_DEL.equals(headerKey)) { + orgaunit.removeSubordinateOrgaUnit(subOrgaUnit); + } else if (TABLE_COL_UP.equals(headerKey)) { + subOrgaUnits.swapWithPrevious(subOrgaUnit); + } else if (TABLE_COL_DOWN.equals(headerKey)) { + subOrgaUnits.swapWithNext(subOrgaUnit); + } + } + + public void headSelected(TableActionEvent e) { + //Nothing now + } + } +} diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitSuperiorOrgaUnitAddForm.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitSuperiorOrgaUnitAddForm.java new file mode 100644 index 000000000..a01ced457 --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitSuperiorOrgaUnitAddForm.java @@ -0,0 +1,113 @@ +package com.arsdigita.cms.contenttypes.ui; + +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.FormSection; +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.cms.ContentType; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.contenttypes.GenericOrganizationalUnit; +import com.arsdigita.cms.contenttypes.GenericOrganizationalUnitSuperiorCollection; +import com.arsdigita.cms.ui.ItemSearchWidget; +import com.arsdigita.cms.ui.authoring.BasicItemForm; + +/** + * + * @author Jens Pelzetter + * @version $Id$ + */ +public class GenericOrganizationalUnitSuperiorOrgaUnitAddForm + extends BasicItemForm + implements FormProcessListener, + FormInitListener { + + private ItemSearchWidget itemSearch; + private final String ITEM_SEARCH = "superiorOrgaUnits"; + private final GenericOrgaUnitSuperiorOrgaUnitAddFormCustomizer customizer; + + public GenericOrganizationalUnitSuperiorOrgaUnitAddForm( + final ItemSelectionModel itemModel, + final GenericOrgaUnitSuperiorOrgaUnitAddFormCustomizer customizer) { + super("SuperiorOrgaUnitsAddForm", itemModel); + this.customizer = customizer; + } + + @Override + protected void addWidgets() { + add(new Label(customizer.getSelectSuperiorOrgaUnitLabel())); + itemSearch = new ItemSearchWidget( + ITEM_SEARCH, + ContentType.findByAssociatedObjectType( + customizer.getSuperiorOrgaUnitType())); + add(itemSearch); + } + + @Override + public void init(final FormSectionEvent fse) throws FormProcessException { + final PageState state = fse.getPageState(); + + setVisible(state, true); + } + + @Override + public void process(final FormSectionEvent fse) throws FormProcessException { + final FormData data = fse.getFormData(); + final PageState state = fse.getPageState(); + final GenericOrganizationalUnit orgaunit = + (GenericOrganizationalUnit) getItemSelectionModel(). + getSelectedObject(state); + + if (getSaveCancelSection().getSaveButton().isSelected(state)) { + GenericOrganizationalUnit supOrgaUnit = + (GenericOrganizationalUnit) data.get( + ITEM_SEARCH); + supOrgaUnit = (GenericOrganizationalUnit) supOrgaUnit. + getContentBundle().getInstance(orgaunit.getLanguage(), true); + + orgaunit.addSuperiorOrgaUnit(orgaunit, customizer.getAssocType()); + } + + init(fse); + } + + @Override + public void validate(final FormSectionEvent fse) throws FormProcessException { + final PageState state = fse.getPageState(); + final FormData data = fse.getFormData(); + + if (data.get(ITEM_SEARCH) == null) { + data.addError(customizer.getNothingSelectedMessage()); + return; + } + + final GenericOrganizationalUnit orgaunit = + (GenericOrganizationalUnit) getItemSelectionModel(). + getSelectedObject(state); + GenericOrganizationalUnit supOrgaUnit = + (GenericOrganizationalUnit) data.get( + ITEM_SEARCH); + if (!(supOrgaUnit.getContentBundle().hasInstance(orgaunit.getLanguage(), + true))) { + data.addError(customizer.getNoSuitableLanguageVariantMessage()); + return; + } + + supOrgaUnit = (GenericOrganizationalUnit) supOrgaUnit.getContentBundle().getInstance(orgaunit.getLanguage(), true); + + if (orgaunit.getID().equals(supOrgaUnit.getID())) { + data.addError(customizer.getAddingToItselfMessage()); + return; + } + + final GenericOrganizationalUnitSuperiorCollection supOrgaUnits = orgaunit.getSuperiorOrgaUnits(); + supOrgaUnits.addFilter(String.format("id = %s", supOrgaUnit.getID().toString())); + if (supOrgaUnits.size() > 0) { + data.addError(customizer.getAlreadyAddedMessage()); + } + supOrgaUnits.close(); + } +} diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitSuperiorOrgaUnitsTable.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitSuperiorOrgaUnitsTable.java new file mode 100644 index 000000000..bf3650a68 --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/ui/GenericOrganizationalUnitSuperiorOrgaUnitsTable.java @@ -0,0 +1,324 @@ +package com.arsdigita.cms.contenttypes.ui; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +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.CMS; +import com.arsdigita.cms.ContentSection; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.contenttypes.GenericOrganizationalUnit; +import com.arsdigita.cms.contenttypes.GenericOrganizationalUnitSuperiorCollection; +import com.arsdigita.cms.dispatcher.ItemResolver; +import com.arsdigita.cms.dispatcher.Utilities; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.persistence.OID; +import com.arsdigita.util.LockableImpl; + +/** + * + * @author Jens Pelzetter + * @version $Id$ + */ +public class GenericOrganizationalUnitSuperiorOrgaUnitsTable extends Table { + + private final String TABLE_COL_EDIT = "table_col_edit"; + private final String TABLE_COL_DEL = "table_col_del"; + private final String TABLE_COL_UP = "table_col_up"; + private final String TABLE_COL_DOWN = "table_col_down"; + private final ItemSelectionModel itemModel; + private final GenericOrgaUnitSuperiorOrgaUnitsTableCustomizer customizer; + + public GenericOrganizationalUnitSuperiorOrgaUnitsTable( + final ItemSelectionModel itemModel, + final GenericOrgaUnitSuperiorOrgaUnitsTableCustomizer customizer) { + super(); + this.itemModel = itemModel; + this.customizer = customizer; + + setEmptyView(new Label(customizer.getEmptyViewLabel())); + + final TableColumnModel columnModel = getColumnModel(); + columnModel.add(new TableColumn(0, + customizer.getNameColumnLabel(), + TABLE_COL_EDIT)); + columnModel.add(new TableColumn(1, + customizer.getDeleteColumnLabel(), + TABLE_COL_DEL)); + columnModel.add(new TableColumn(2, + customizer.getUpColumnLabel(), + TABLE_COL_UP)); + columnModel.add(new TableColumn(3, + customizer.getDownColumnLabel(), + TABLE_COL_DOWN)); + + setModelBuilder(new ModelBuilder(itemModel, customizer)); + + columnModel.get(0).setCellRenderer(new EditCellRenderer()); + columnModel.get(1).setCellRenderer(new DeleteCellRenderer()); + columnModel.get(2).setCellRenderer(new UpCellRenderer()); + columnModel.get(3).setCellRenderer(new DownCellRenderer()); + + addTableActionListener(new ActionListener()); + } + + private class ModelBuilder extends LockableImpl implements TableModelBuilder { + + private final ItemSelectionModel itemModel; + private final GenericOrgaUnitSuperiorOrgaUnitsTableCustomizer customizer; + + public ModelBuilder( + final ItemSelectionModel itemModel, + final GenericOrgaUnitSuperiorOrgaUnitsTableCustomizer customizer) { + this.itemModel = itemModel; + this.customizer = customizer; + } + + @Override + public TableModel makeModel(final Table table, final PageState state) { + table.getRowSelectionModel().clearSelection(state); + final GenericOrganizationalUnit orgaunit = + (GenericOrganizationalUnit) itemModel. + getSelectedObject(state); + return new Model(table, state, orgaunit, customizer); + } + } + + private class Model implements TableModel { + + private final Table table; + private final GenericOrganizationalUnitSuperiorCollection superiorOrgaUnits; + private final GenericOrgaUnitSuperiorOrgaUnitsTableCustomizer customizer; + + public Model(final Table table, + final PageState state, + final GenericOrganizationalUnit orgaunit, + final GenericOrgaUnitSuperiorOrgaUnitsTableCustomizer customizer) { + this.table = table; + superiorOrgaUnits = orgaunit.getSuperiorOrgaUnits(); + if ((customizer.getAssocType() != null) + && !(customizer.getAssocType().isEmpty())) { + superiorOrgaUnits.addFilter(String.format("assocType = '%s", + customizer. + getAssocType())); + } + this.customizer = customizer; + } + + @Override + public int getColumnCount() { + return table.getColumnModel().size(); + } + + @Override + public boolean nextRow() { + boolean ret; + + if ((superiorOrgaUnits != null) && superiorOrgaUnits.next()) { + ret = true; + } else { + ret = false; + } + + return ret; + } + + public Object getElementAt(final int columnIndex) { + switch (columnIndex) { + case 0: + return superiorOrgaUnits.getTitle(); + case 1: + return customizer.getDeleteLabel(); + case 2: + return customizer.getUpLabel(); + case 3: + return customizer.getDownLabel(); + default: + return null; + } + } + + public Object getKeyAt(int columnIndex) { + return superiorOrgaUnits.getOID(); + } + } + + private class EditCellRenderer + extends LockableImpl + implements TableCellRenderer { + + public Component getComponent(final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int column) { + final com.arsdigita.cms.SecurityManager securityManager = Utilities. + getSecurityManager(state); + final GenericOrganizationalUnit superiorOrgaUnit = + (GenericOrganizationalUnit) DomainObjectFactory. + newInstance((OID) key); + + final boolean canEdit = securityManager.canAccess( + state.getRequest(), + com.arsdigita.cms.SecurityManager.EDIT_ITEM, + superiorOrgaUnit); + + if (canEdit) { + final ContentSection section = CMS.getContext(). + getContentSection(); + final ItemResolver resolver = section.getItemResolver(); + final Link link = new Link( + String.format("%s (%s)", + value.toString(), + superiorOrgaUnit.getLanguage()), + resolver.generateItemURL(state, + superiorOrgaUnit, + section, + superiorOrgaUnit.getVersion())); + return link; + } else { + final Label label = new Label(String.format( + "%s (%s)", + value.toString(), + superiorOrgaUnit.getLanguage())); + return label; + } + } + } + + private class DeleteCellRenderer + extends LockableImpl + implements TableCellRenderer { + + @Override + public Component getComponent(final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int column) { + final com.arsdigita.cms.SecurityManager securityManager = Utilities. + getSecurityManager(state); + final GenericOrganizationalUnit orgaunit = + (GenericOrganizationalUnit) itemModel. + getSelectedObject(state); + + + boolean canEdit = securityManager.canAccess( + state.getRequest(), + com.arsdigita.cms.SecurityManager.EDIT_ITEM, + orgaunit); + + if (canEdit) { + final ControlLink link = new ControlLink(value.toString()); + link.setConfirmation(customizer.getConfirmRemoveLabel()); + return link; + } else { + final Label label = new Label(""); + return label; + } + } + } + + private class UpCellRenderer + extends LockableImpl + implements TableCellRenderer { + + public Component getComponent(final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int column) { + + if (row == 0) { + final Label label = new Label(""); + return label; + } else { + final ControlLink link = + new ControlLink(customizer.getUpLabel()); + return link; + } + } + } + + private class DownCellRenderer + extends LockableImpl + implements TableCellRenderer { + + @Override + public Component getComponent(final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int column) { + + final GenericOrganizationalUnit orgaunit = + (GenericOrganizationalUnit) itemModel. + getSelectedObject(state); + final GenericOrganizationalUnitSuperiorCollection supOrgaUnits = + orgaunit. + getSuperiorOrgaUnits(); + + if ((supOrgaUnits.size() - 1) == row) { + final Label label = new Label(""); + return label; + } else { + final ControlLink link = + new ControlLink(customizer.getDownLabel()); + return link; + } + } + } + + private class ActionListener implements TableActionListener { + + @Override + public void cellSelected(final TableActionEvent event) { + final PageState state = event.getPageState(); + + final GenericOrganizationalUnit orgaunit = + (GenericOrganizationalUnit) itemModel. + getSelectedObject(state); + final GenericOrganizationalUnit supOrgaUnit = + (GenericOrganizationalUnit) DomainObjectFactory. + newInstance((OID) event.getRowKey()); + final GenericOrganizationalUnitSuperiorCollection supOrgaUnits = + orgaunit. + getSuperiorOrgaUnits(); + + final TableColumn column = getColumnModel().get(event.getColumn(). + intValue()); + final String headerKey = column.getHeaderKey().toString(); + if (TABLE_COL_EDIT.equals(headerKey)) { + //Nothing now + } else if(TABLE_COL_DEL.equals(headerKey)) { + orgaunit.removeSuperiorOrgaUnit(supOrgaUnit); + } else if (TABLE_COL_UP.equals(headerKey)) { + supOrgaUnits.swapWithPrevious(supOrgaUnit); + } else if(TABLE_COL_DOWN.equals(headerKey)) { + supOrgaUnits.swapWithNext(supOrgaUnit); + } + } + + @Override + public void headSelected(final TableActionEvent event) { + //Nothing now + } + } +} diff --git a/ccm-sci-types-organization/application.xml b/ccm-sci-types-organization/application.xml index 364197122..4527ba02b 100644 --- a/ccm-sci-types-organization/application.xml +++ b/ccm-sci-types-organization/application.xml @@ -6,8 +6,9 @@ release="1" webapp="ROOT"> - - + + + diff --git a/ccm-sci-types-organization/src/WEB-INF/traversal-adapters/com/arsdigita/cms/contenttypes/SciProject.xml b/ccm-sci-types-organization/src/WEB-INF/traversal-adapters/com/arsdigita/cms/contenttypes/SciProject.xml index 4d7a99ee3..b37af9316 100644 --- a/ccm-sci-types-organization/src/WEB-INF/traversal-adapters/com/arsdigita/cms/contenttypes/SciProject.xml +++ b/ccm-sci-types-organization/src/WEB-INF/traversal-adapters/com/arsdigita/cms/contenttypes/SciProject.xml @@ -19,7 +19,7 @@ - + -->