diff --git a/ccm-cms/pdl/com/arsdigita/content-section/ContentType.pdl b/ccm-cms/pdl/com/arsdigita/content-section/ContentType.pdl index c104a00eb..8a771c4c0 100755 --- a/ccm-cms/pdl/com/arsdigita/content-section/ContentType.pdl +++ b/ccm-cms/pdl/com/arsdigita/content-section/ContentType.pdl @@ -27,6 +27,11 @@ object type ContentType extends ACSObject { String[1..1] label = content_types.label VARCHAR(1000); String[0..1] description = content_types.description VARCHAR(4000); String[0..1] className = content_types.classname VARCHAR(200); + // Quasimodo: Store the information about ancenstors and siblings, so we + // can make use of extending content types + String[0..1] ancestors = content_types.ancestors VARCHAR(2000); + String[0..1] siblings = content_types.siblings VARCHAR(2000); + Boolean[1..1] isInternal = content_types.is_internal CHAR(1); BigDecimal[0..1] itemFormID = content_types.item_form_id INTEGER; AuthoringKit[0..1] authoringKit = join content_types.type_id @@ -59,7 +64,7 @@ association { do { select t.type_id, t.object_type, t.label, t.description, t.classname, - t.is_internal, t.item_form_id + t.ancestors, t.siblings, t.is_internal, t.item_form_id from content_types t, content_section_type_map m, authoring_kits a where @@ -73,6 +78,8 @@ association { creatableContentTypes.label = t.label; creatableContentTypes.description = t.description; creatableContentTypes.className = t.classname; + creatableContentTypes.ancestors = t.ancestors; + creatableContentTypes.siblings = t.siblings; creatableContentTypes.isInternal = t.is_internal; creatableContentTypes.itemFormID = t.item_form_id; } @@ -105,7 +112,7 @@ association { do { select t.type_id, t.object_type, t.label, t.description, t.classname, - t.is_internal, t.item_form_id + t.ancestors, t.siblings, t.is_internal, t.item_form_id from content_types t where @@ -119,6 +126,8 @@ association { notAssociatedContentTypes.label = t.label; notAssociatedContentTypes.description = t.description; notAssociatedContentTypes.className = t.classname; + notAssociatedContentTypes.ancestors = t.ancestors; + notAssociatedContentTypes.siblings = t.siblings; notAssociatedContentTypes.isInternal = t.is_internal; notAssociatedContentTypes.itemFormID = t.item_form_id; } @@ -147,7 +156,8 @@ query registeredContentTypes { do { select t.type_id, t.object_type, t.label, - t.description, t.classname, t.is_internal, t.item_form_id + t.description, t.classname, t.ancestors, t.siblings, + t.is_internal, t.item_form_id from content_types t where t.is_internal = '0' and exists (select 1 from content_section_type_map @@ -158,6 +168,8 @@ query registeredContentTypes { type.label = t.label; type.description = t.description; type.className = t.classname; + type.ancestors = t.ancestors; + type.siblings = t.siblings; type.isInternal = t.is_internal; type.itemFormID = t.item_form_id; } diff --git a/ccm-cms/sql/ccm-cms/default/content-section/table-content_types.sql b/ccm-cms/sql/ccm-cms/default/content-section/table-content_types.sql index 1d306f0c4..2bbc3edd4 100755 --- a/ccm-cms/sql/ccm-cms/default/content-section/table-content_types.sql +++ b/ccm-cms/sql/ccm-cms/default/content-section/table-content_types.sql @@ -29,6 +29,8 @@ create table content_types ( label varchar(1000) not null, description varchar(4000), classname varchar(200), + ancestors varchar(2000), + siblings varchar(2000), is_internal char(1) default '0' not null constraint content_types_is_internal_ck check ( is_internal in ('0', '1') ), diff --git a/ccm-cms/src/WEB-INF/basetypes/Address.xml b/ccm-cms/src/WEB-INF/basetypes/Address.xml new file mode 100644 index 000000000..6f7a301f0 --- /dev/null +++ b/ccm-cms/src/WEB-INF/basetypes/Address.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + diff --git a/ccm-cms/src/WEB-INF/basetypes/Article.xml b/ccm-cms/src/WEB-INF/basetypes/Article.xml new file mode 100644 index 000000000..f84a382eb --- /dev/null +++ b/ccm-cms/src/WEB-INF/basetypes/Article.xml @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/ccm-cms/src/WEB-INF/basetypes/Contact.xml b/ccm-cms/src/WEB-INF/basetypes/Contact.xml new file mode 100644 index 000000000..8467b8a66 --- /dev/null +++ b/ccm-cms/src/WEB-INF/basetypes/Contact.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + diff --git a/ccm-cms/src/WEB-INF/basetypes/Person.xml b/ccm-cms/src/WEB-INF/basetypes/Person.xml new file mode 100644 index 000000000..d63c27553 --- /dev/null +++ b/ccm-cms/src/WEB-INF/basetypes/Person.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + diff --git a/ccm-cms/src/WEB-INF/resources/cms-item-adapters.xml b/ccm-cms/src/WEB-INF/resources/cms-item-adapters.xml index 77c93d0d6..1a3920aeb 100755 --- a/ccm-cms/src/WEB-INF/resources/cms-item-adapters.xml +++ b/ccm-cms/src/WEB-INF/resources/cms-item-adapters.xml @@ -1,235 +1,235 @@ - - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ccm-cms/src/com/arsdigita/cms/ContentItem.java b/ccm-cms/src/com/arsdigita/cms/ContentItem.java index 750dc4aea..6f0e486c3 100755 --- a/ccm-cms/src/com/arsdigita/cms/ContentItem.java +++ b/ccm-cms/src/com/arsdigita/cms/ContentItem.java @@ -387,7 +387,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { * override this method to return the correct value */ public String getBaseDataObjectType() { - return BASE_DATA_OBJECT_TYPE; + return this.BASE_DATA_OBJECT_TYPE; } /** @@ -553,6 +553,18 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { m_reporter.mutated("contentType"); } + public boolean isContentType(ContentType type) { + + try { + // Try to cast this contentItem to the desired content type + // This will succeed if this ci is of the type or a subclass + Class.forName(type.getClassName()).cast(this); + return true; + } catch (Exception ex) { + return false; + } + } + /** * Returns the content section to which this item belongs. * Fetches the denormalized content section of an item. If one is @@ -684,14 +696,6 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } } - //add filter for ancestor check - int iLength; - if (includeSelf) { - iLength = ids.length(); - } else { - iLength = ids.length() - 1; - } - //add list of ancestors split by "/" character ArrayList ancestors = new ArrayList(); int iIndex = 0; diff --git a/ccm-cms/src/com/arsdigita/cms/ContentType.java b/ccm-cms/src/com/arsdigita/cms/ContentType.java index 209eed469..ffaeb06ee 100755 --- a/ccm-cms/src/com/arsdigita/cms/ContentType.java +++ b/ccm-cms/src/com/arsdigita/cms/ContentType.java @@ -57,16 +57,17 @@ import java.net.MalformedURLException; public class ContentType extends ACSObject { public static final String BASE_DATA_OBJECT_TYPE = - "com.arsdigita.cms.ContentType"; - - public static final String OBJECT_TYPE = "associatedObjectType"; - public static final String LABEL = "label"; - public static final String DESCRIPTION = "description"; - public static final String CLASSNAME = "className"; - public static final String IS_INTERNAL = "isInternal"; - public static final String AUTHORING_KIT = "authoringKit"; - public static final String ITEM_FORM_ID = "itemFormID"; - public static final String ITEM_FORM = "itemForm"; + "com.arsdigita.cms.ContentType"; + public static final String OBJECT_TYPE = "associatedObjectType"; + public static final String LABEL = "label"; + public static final String DESCRIPTION = "description"; + public static final String CLASSNAME = "className"; + public static final String IS_INTERNAL = "isInternal"; + public static final String AUTHORING_KIT = "authoringKit"; + public static final String ITEM_FORM_ID = "itemFormID"; + public static final String ITEM_FORM = "itemForm"; + public static final String ANCESTORS = "ancestors"; + public static final String SIBLINGS = "siblings"; /** * Default constructor. This creates a new folder. @@ -112,12 +113,14 @@ public class ContentType extends ACSObject { * @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; } + @Override protected void beforeSave() { - if ( isInternal() == null ) { + if (isInternal() == null) { setInternal(false); } super.beforeSave(); @@ -144,7 +147,6 @@ public class ContentType extends ACSObject { set(OBJECT_TYPE, objType); } - /** * Fetches the label for the content type. * @@ -229,7 +231,7 @@ public class ContentType extends ACSObject { * false otherwise */ public void setInternal(boolean isInternal) { - set(IS_INTERNAL, ( isInternal ? Boolean.TRUE : Boolean.FALSE )); + set(IS_INTERNAL, (isInternal ? Boolean.TRUE : Boolean.FALSE)); } /** @@ -265,16 +267,16 @@ public class ContentType extends ACSObject { */ public AuthoringKit createAuthoringKit(String createComponent) { - if ( getAuthoringKit() == null ) { + if (getAuthoringKit() == null) { AuthoringKit kit = new AuthoringKit(); kit.setContentType(this); - if ( createComponent != null ) { + if (createComponent != null) { kit.setCreateComponent(createComponent); } return kit; } else { throw new RuntimeException( - "An AuthorigKit exists for this ContentType."); + "An AuthorigKit exists for this ContentType."); } } @@ -317,12 +319,132 @@ public class ContentType extends ACSObject { } + /** + * Add an ancestor to the list of siblings, if not already in the list + * @param newAncestor ID of the ancestor to add + */ + public void addAncestor(BigDecimal newAncestor) { + // Get the list of siblings from db + String ancestors = (String) get(ANCESTORS); + + // Only add if the newSibling in not yet in the list + if (ancestors == null) { + ancestors = newAncestor.toString(); + } else if (!ancestors.contains(newAncestor.toString())) { + if (ancestors.length() == 0) { + // First entry in list + ancestors = newAncestor.toString(); + } else { + // Additional entry in the list + ancestors += "/" + newAncestor.toString(); + } + } + + // Write new data back to db + set(ANCESTORS, ancestors); + } + + /** + * Remove an ancestor id from the list of siblings + * @param ancestor ID to be removed + */ + public void delAncestor(BigDecimal ancestor) { + // Get the list of siblings from db + String ancestors = (String) get(ANCESTORS); + + // Only try to remove from a non-empty string + if (ancestors != null && ancestors.length() > 0) { + + // Remove ancestor ID from list + ancestors.replace(ancestor.toString(), ""); + // Delete the additional slash + ancestors.replace("//", "/"); + + // If the list only contains a single slash, + // we have just removed the last list entry, so the list is empty + if (ancestors.equals("/")) { + ancestors = ""; + } + } + + // Write new data back to db + set(ANCESTORS, ancestors); + } + + /** + * Get the list of ancestors + * @return + */ + public String getAncestors() { + return (String) get(ANCESTORS); + } + + /** + * Add a sibling to the list of siblings, if not already in list + * @param newSibling ID of the sibling to add + */ + public void addSiblings(BigDecimal newSibling) { + + // Get the list of siblings from db + String siblings = (String) get(SIBLINGS); + + // Only add if the newSibling in not yet in the list + if (siblings == null) { + siblings = newSibling.toString(); + } else if (!siblings.contains(newSibling.toString())) { + + if (siblings.length() == 0) { + // First entry in list + siblings = newSibling.toString(); + } else { + // Additional entry in the list + siblings += "/" + newSibling.toString(); + } + } + + // Write new data back to db + set(SIBLINGS, siblings); + } + + /** + * Get the list of siblings + * @return + */ + public String getSiblings() { + return (String) get(SIBLINGS); + } + + /** + * Remove a sibling from the list of siblings + * @param sibling ID to be removed + */ + public void delSiblings(BigDecimal sibling) { + // Get the list of siblings from db + String siblings = (String) get(SIBLINGS); + + // Only try to remove from a non-empty string + if (siblings != null && siblings.length() > 0) { + + // Remove ancestor ID from list + siblings.replace(sibling.toString(), ""); + // Delete the additional slash + siblings.replace("//", "/"); + + // If the list only contains a single slash, + // we have just removed the last list entry, so the list is empty + if (siblings.equals("/")) { + siblings = ""; + } + } + + // Write new data back to db + set(SIBLINGS, siblings); + } ////////////////////////////////////// // // Fetching/Finding content types. // - /** * Find the content type with the associated with the object type. * @@ -330,20 +452,40 @@ public class ContentType extends ACSObject { * @return The content type associated with the object type */ public static ContentType findByAssociatedObjectType(String objType) - throws DataObjectNotFoundException { + throws DataObjectNotFoundException { ContentTypeCollection types = getAllContentTypes(); types.addFilter("associatedObjectType = :type").set("type", objType); - if ( types.next() ) { + + + + + if (types.next()) { ContentType type = types.getContentType(); types.close(); + + + + return type; + + + + } else { // no match types.close(); + + + + throw new DataObjectNotFoundException( - "No matching content type for object type " + objType); + "No matching content type for object type " + objType); + + + + } } @@ -355,6 +497,10 @@ public class ContentType extends ACSObject { */ public static ContentTypeCollection getAllContentTypes() { return getAllContentTypes(true); + + + + } /** @@ -364,6 +510,10 @@ public class ContentType extends ACSObject { */ public static ContentTypeCollection getUserDefinedContentTypes() { return getAllContentTypes(false); + + + + } /** @@ -371,13 +521,24 @@ public class ContentType extends ACSObject { * content types. If false, only fetch all user-defined content types. */ private static ContentTypeCollection getAllContentTypes(boolean internal) { - DataCollection da = SessionManager.getSession().retrieve - (BASE_DATA_OBJECT_TYPE); + DataCollection da = SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE); ContentTypeCollection types = new ContentTypeCollection(da); - if ( !internal ) { + + + + + if (!internal) { types.addFilter("isInternal = '0'"); + + + + } return types; + + + + } /** @@ -390,13 +551,18 @@ public class ContentType extends ACSObject { final String query = "com.arsdigita.cms.registeredContentTypes"; DataQuery dq = SessionManager.getSession().retrieveQuery(query); DataCollection dc = new DataQueryDataCollectionAdapter(dq, "type"); + + + + return new ContentTypeCollection(dc); + + + + } - - private static List s_xsl = new ArrayList(); - - + /** * NB this interface is liable to change. * @@ -405,8 +571,12 @@ public class ContentType extends ACSObject { * @param path the path relative to the server root */ public static void registerXSLFile(ContentType type, - String path) { + String path) { s_xsl.add(new XSLEntry(type, path)); + + + + } /** @@ -417,19 +587,40 @@ public class ContentType extends ACSObject { * @param path the path relative to the server root */ public static void unregisterXSLFile(ContentType type, - String path) { + String path) { s_xsl.remove(new XSLEntry(type, path)); + + + + } - + /** * Gets an iterator of java.net.URL objects for * all registered XSL files */ public static Iterator getXSLFileURLs() { return new EntryIterator(s_xsl.iterator()); + + + + + + + + + + + + + + + + } private static class EntryIterator implements Iterator { + private Iterator m_inner; public EntryIterator(Iterator inner) { @@ -439,53 +630,56 @@ public class ContentType extends ACSObject { public boolean hasNext() { return m_inner.hasNext(); } - + public Object next() { - XSLEntry entry = (XSLEntry)m_inner.next(); + XSLEntry entry = (XSLEntry) m_inner.next(); String path = entry.getPath(); - + try { return new URL(Web.getConfig().getDefaultScheme(), - Web.getConfig().getHost().getName(), - Web.getConfig().getHost().getPort(), - path); + Web.getConfig().getHost().getName(), + Web.getConfig().getHost().getPort(), + path); } catch (MalformedURLException ex) { throw new UncheckedWrapperException("path malformed" + path, ex); } } - + public void remove() { m_inner.remove(); } } private static class XSLEntry { + private ContentType m_type; private String m_path; - + public XSLEntry(ContentType type, - String path) { + String path) { m_type = type; m_path = path; } - - public ContentType getType(){ + + public ContentType getType() { return m_type; } public String getPath() { return m_path; } - + + @Override public boolean equals(Object o) { if (!(o instanceof XSLEntry)) { return false; } - XSLEntry e = (XSLEntry)o; - return m_path.equals(e.m_path) && - m_type.equals(e.m_type); + XSLEntry e = (XSLEntry) o; + return m_path.equals(e.m_path) + && m_type.equals(e.m_type); } - + + @Override public int hashCode() { return m_path.hashCode() + m_type.hashCode(); } diff --git a/ccm-cms/src/com/arsdigita/cms/basetypes/ui/AddressPropertiesStep.java b/ccm-cms/src/com/arsdigita/cms/basetypes/ui/AddressPropertiesStep.java index 3061a08d6..64cc0f8cd 100644 --- a/ccm-cms/src/com/arsdigita/cms/basetypes/ui/AddressPropertiesStep.java +++ b/ccm-cms/src/com/arsdigita/cms/basetypes/ui/AddressPropertiesStep.java @@ -58,8 +58,8 @@ public class AddressPropertiesStep extends SimpleEditStep { public static Component getAddressPropertySheet(ItemSelectionModel itemModel) { DomainObjectPropertySheet sheet = new DomainObjectPropertySheet(itemModel); - sheet.add((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.name").localize(), Address.NAME); - sheet.add((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.title").localize(), Address.TITLE); + sheet.add((String) GlobalizationUtil.globalize("cms.contenttypes.ui.name").localize(), Address.NAME); + sheet.add((String) GlobalizationUtil.globalize("cms.contenttypes.ui.title").localize(), Address.TITLE); sheet.add((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.address.address").localize(), Address.ADDRESS); sheet.add((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.address.postal_code").localize(), Address.POSTAL_CODE); sheet.add((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.address.city").localize(), Address.CITY); diff --git a/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactAddressPropertiesStep.java b/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactAddressPropertiesStep.java index 6c7421928..94cad95e3 100644 --- a/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactAddressPropertiesStep.java +++ b/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactAddressPropertiesStep.java @@ -73,17 +73,17 @@ public class ContactAddressPropertiesStep extends SimpleEditStep { DomainObjectPropertySheet sheet = new DomainObjectPropertySheet(itemModel); - sheet.add((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.baseAddress.address").localize(), "address." + Address.ADDRESS); + sheet.add((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.address.address").localize(), "address." + Address.ADDRESS); if (!Contact.getConfig().getHideAddressPostalCode()) { - sheet.add((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.baseAddress.postal_code").localize(), "address." + Address.POSTAL_CODE); + sheet.add((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.address.postal_code").localize(), "address." + Address.POSTAL_CODE); } - sheet.add((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.baseAddress.city").localize(), "address." + Address.CITY); + sheet.add((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.address.city").localize(), "address." + Address.CITY); if (!Contact.getConfig().getHideAddressState()) { - sheet.add((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.baseAddress.state").localize(), "address." + Address.STATE); + sheet.add((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.address.state").localize(), "address." + Address.STATE); } if (!Contact.getConfig().getHideAddressCountry()) { - sheet.add((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.baseAddress.iso_country_code").localize(), + sheet.add((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.address.iso_country_code").localize(), "address." + Address.ISO_COUNTRY_CODE, new DomainObjectPropertySheet.AttributeFormatter() { diff --git a/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactAttachAddressPropertyForm.java b/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactAttachAddressPropertyForm.java index a06b19d6d..4e66a130d 100644 --- a/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactAttachAddressPropertyForm.java +++ b/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactAttachAddressPropertyForm.java @@ -79,7 +79,7 @@ public class ContactAttachAddressPropertyForm extends BasicPageForm implements F @Override public void addWidgets() { add(new Label((String)BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.contact.select_address").localize())); - this.m_itemSearch = new ItemSearchWidget(ITEM_SEARCH, ContentType.findByAssociatedObjectType("com.arsdigita.cms.basetypes.BaseAddress")); + this.m_itemSearch = new ItemSearchWidget(ITEM_SEARCH, ContentType.findByAssociatedObjectType("com.arsdigita.cms.basetypes.Address")); add(this.m_itemSearch); } diff --git a/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactEditAddressPropertyForm.java b/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactEditAddressPropertyForm.java index 487697f54..f25c3e305 100644 --- a/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactEditAddressPropertyForm.java +++ b/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactEditAddressPropertyForm.java @@ -6,7 +6,6 @@ * To change this template, choose Tools | Template Manager * and open the template in the editor. */ - package com.arsdigita.cms.basetypes.ui; import com.arsdigita.bebop.FormData; @@ -43,17 +42,14 @@ import org.apache.log4j.Logger; * @author quasi */ public class ContactEditAddressPropertyForm extends BasicPageForm implements FormProcessListener, FormInitListener, FormSubmissionListener { - + private static final Logger logger = Logger.getLogger(ContactPropertyForm.class); - private ContactAddressPropertiesStep m_step; - public static final String ADDRESS = Address.ADDRESS; public static final String POSTAL_CODE = Address.POSTAL_CODE; public static final String CITY = Address.CITY; public static final String STATE = Address.STATE; public static final String ISO_COUNTRY_CODE = Address.ISO_COUNTRY_CODE; - /** * ID of the form */ @@ -64,7 +60,7 @@ public class ContactEditAddressPropertyForm extends BasicPageForm implements For * * @param itemModel */ - public ContactEditAddressPropertyForm(ItemSelectionModel itemModel) { + public ContactEditAddressPropertyForm(ItemSelectionModel itemModel) { this(itemModel, null); } @@ -82,61 +78,61 @@ public class ContactEditAddressPropertyForm extends BasicPageForm implements For @Override public void addWidgets() { - add(new Label((String)BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.baseAddress.address").localize())); - ParameterModel addressParam = new StringParameter(ADDRESS); - addressParam.addParameterListener( new NotNullValidationListener( ) ); - addressParam.addParameterListener( new StringInRangeValidationListener(0, 1000) ); - TextArea address = new TextArea(addressParam); + add(new Label((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.baseAddress.address").localize())); + ParameterModel addressParam = new StringParameter(ADDRESS); + addressParam.addParameterListener(new NotNullValidationListener()); + addressParam.addParameterListener(new StringInRangeValidationListener(0, 1000)); + TextArea address = new TextArea(addressParam); address.setRows(5); address.setCols(30); - add(address); + add(address); - if(!Contact.getConfig().getHideAddressPostalCode()) { - add(new Label((String)BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.baseAddress.postal_code").localize())); + if (!Contact.getConfig().getHideAddressPostalCode()) { + add(new Label((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.baseAddress.postal_code").localize())); ParameterModel postalCodeParam = new StringParameter(POSTAL_CODE); TextField postalCode = new TextField(postalCodeParam); /* XXX NumberListener ?*/ add(postalCode); } - add(new Label((String)BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.baseAddress.city").localize())); - ParameterModel cityParam = new StringParameter(CITY); - TextField city = new TextField(cityParam); - add(city); + add(new Label((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.baseAddress.city").localize())); + ParameterModel cityParam = new StringParameter(CITY); + TextField city = new TextField(cityParam); + add(city); - if(!Contact.getConfig().getHideAddressState()) { - add(new Label((String)BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.baseAddress.state").localize())); + if (!Contact.getConfig().getHideAddressState()) { + add(new Label((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.baseAddress.state").localize())); ParameterModel stateParam = new StringParameter(STATE); TextField state = new TextField(stateParam); add(state); } - + if (!Contact.getConfig().getHideAddressCountry()) { - add(new Label((String)BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.baseAddress.iso_country_code").localize())); + add(new Label((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.baseAddress.iso_country_code").localize())); ParameterModel countryParam = new StringParameter(ISO_COUNTRY_CODE); countryParam.addParameterListener(new StringInRangeValidationListener(0, 2)); - + SingleSelect country = new SingleSelect(countryParam); - country.addOption(new Option("", new Label((String)BasetypesGlobalizationUtil.globalize("cms.ui.select_one" ).localize()))); + country.addOption(new Option("", new Label((String) BasetypesGlobalizationUtil.globalize("cms.ui.select_one").localize()))); Iterator countries = Address.getSortedListOfCountries(null).entrySet().iterator(); - while(countries.hasNext()) { - Map.Entry elem = (Map.Entry)countries.next(); + while (countries.hasNext()) { + Map.Entry elem = (Map.Entry) countries.next(); country.addOption(new Option(elem.getValue().toString(), elem.getKey().toString())); } - + country.addValidationListener( - new ParameterListener() { - public void validate(ParameterEvent e) throws FormProcessException { - ParameterData data = e.getParameterData(); - String isoCode = (String) data.getValue() ; - if (isoCode == null || isoCode.length() == 0) { - data.addError((String)BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.address.error_iso_country").localize()); + new ParameterListener() { + + public void validate(ParameterEvent e) throws FormProcessException { + ParameterData data = e.getParameterData(); + String isoCode = (String) data.getValue(); + if (isoCode == null || isoCode.length() == 0) { + data.addError((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.address.error_iso_country").localize()); + } } - } - } - ); + }); add(country); } @@ -144,46 +140,51 @@ public class ContactEditAddressPropertyForm extends BasicPageForm implements For } public void init(FormSectionEvent fse) { - FormData data = fse.getFormData(); + FormData data = fse.getFormData(); PageState state = fse.getPageState(); - Contact contact = (Contact)getItemSelectionModel().getSelectedObject(state); - - if(contact.getAddress() != null) { + Contact contact = (Contact) getItemSelectionModel().getSelectedObject(state); + + if (contact.getAddress() != null) { data.put(ADDRESS, contact.getAddress().getAddress()); data.put(POSTAL_CODE, contact.getAddress().getPostalCode()); data.put(CITY, contact.getAddress().getCity()); data.put(STATE, contact.getAddress().getState()); - if(!Address.getConfig().getHideCountryCodeSelection()) { + if (!Address.getConfig().getHideCountryCodeSelection()) { data.put(ISO_COUNTRY_CODE, contact.getAddress().getIsoCountryCode()); } } } public void submitted(FormSectionEvent fse) { - if (m_step != null && - getSaveCancelSection().getCancelButton().isSelected(fse.getPageState())) { - m_step.cancelStreamlinedCreation(fse.getPageState()); - } + if (m_step != null + && getSaveCancelSection().getCancelButton().isSelected(fse.getPageState())) { + m_step.cancelStreamlinedCreation(fse.getPageState()); + } } public void process(FormSectionEvent fse) { - FormData data = fse.getFormData(); + FormData data = fse.getFormData(); PageState state = fse.getPageState(); - Contact contact = (Contact)getItemSelectionModel().getSelectedObject(state); + Contact contact = (Contact) getItemSelectionModel().getSelectedObject(state); - if (contact.getAddress() != null && - getSaveCancelSection().getSaveButton().isSelected(fse.getPageState())) { - contact.getAddress().setAddress((String)data.get(ADDRESS)); - contact.getAddress().setPostalCode((String)data.get(POSTAL_CODE)); - contact.getAddress().setCity((String)data.get(CITY)); - contact.getAddress().setState((String)data.get(STATE)); - contact.getAddress().setIsoCountryCode((String)data.get(ISO_COUNTRY_CODE)); - - contact.getAddress().save(); - } - - if (m_step != null) { - m_step.maybeForwardToNextStep(fse.getPageState()); - } + if (getSaveCancelSection().getSaveButton().isSelected(fse.getPageState())) { + if (contact.getAddress() == null) { + contact.setAddress(new Address()); + contact.getAddress().setName("Address for " + contact.getName() + "(" + contact.getID() + ")"); + contact.getAddress().setTitle("Address for " + contact.getName() + "(" + contact.getID() + ")"); + } + + contact.getAddress().setAddress((String) data.get(ADDRESS)); + contact.getAddress().setPostalCode((String) data.get(POSTAL_CODE)); + contact.getAddress().setCity((String) data.get(CITY)); + contact.getAddress().setState((String) data.get(STATE)); + contact.getAddress().setIsoCountryCode((String) data.get(ISO_COUNTRY_CODE)); + + contact.getAddress().save(); + } + + if (m_step != null) { + m_step.maybeForwardToNextStep(fse.getPageState()); + } } -} \ No newline at end of file +} diff --git a/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactEditPersonPropertyForm.java b/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactEditPersonPropertyForm.java index 8afee36d3..81bad7f3a 100644 --- a/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactEditPersonPropertyForm.java +++ b/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactEditPersonPropertyForm.java @@ -6,7 +6,6 @@ * To change this template, choose Tools | Template Manager * and open the template in the editor. */ - package com.arsdigita.cms.basetypes.ui; import com.arsdigita.bebop.FormData; @@ -34,16 +33,13 @@ import org.apache.log4j.Logger; * @author quasi */ public class ContactEditPersonPropertyForm extends BasicPageForm implements FormProcessListener, FormInitListener, FormSubmissionListener { - + private static final Logger logger = Logger.getLogger(ContactPropertyForm.class); - private ContactPersonPropertiesStep m_step; - public static final String SURNAME = Person.SURNAME; public static final String GIVENNAME = Person.GIVENNAME; public static final String TITLEPRE = Person.TITLEPRE; public static final String TITLEPOST = Person.TITLEPOST; - /** * ID of the form */ @@ -54,7 +50,7 @@ public class ContactEditPersonPropertyForm extends BasicPageForm implements Form * * @param itemModel */ - public ContactEditPersonPropertyForm(ItemSelectionModel itemModel) { + public ContactEditPersonPropertyForm(ItemSelectionModel itemModel) { this(itemModel, null); } @@ -72,39 +68,39 @@ public class ContactEditPersonPropertyForm extends BasicPageForm implements Form @Override public void addWidgets() { - add(new Label((String)BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.person.surname").localize())); - ParameterModel surnameParam = new StringParameter(SURNAME); - surnameParam.addParameterListener( new NotNullValidationListener( ) ); - surnameParam.addParameterListener( new StringInRangeValidationListener(0, 1000) ); - TextField surname = new TextField(surnameParam); - add(surname); + add(new Label((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.person.surname").localize())); + ParameterModel surnameParam = new StringParameter(SURNAME); + surnameParam.addParameterListener(new NotNullValidationListener()); + surnameParam.addParameterListener(new StringInRangeValidationListener(0, 1000)); + TextField surname = new TextField(surnameParam); + add(surname); - add(new Label((String)BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.person.givenname").localize())); - ParameterModel givennameParam = new StringParameter(GIVENNAME); - givennameParam.addParameterListener( new NotNullValidationListener( ) ); - givennameParam.addParameterListener( new StringInRangeValidationListener(0, 1000) ); - TextField givenname = new TextField(givennameParam); - add(givenname); + add(new Label((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.person.givenname").localize())); + ParameterModel givennameParam = new StringParameter(GIVENNAME); + givennameParam.addParameterListener(new NotNullValidationListener()); + givennameParam.addParameterListener(new StringInRangeValidationListener(0, 1000)); + TextField givenname = new TextField(givennameParam); + add(givenname); - add(new Label((String)BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.person.titlepre").localize())); - ParameterModel titlepreParam = new StringParameter(TITLEPRE); - titlepreParam.addParameterListener( new StringInRangeValidationListener(0, 1000) ); - TextField titlepre = new TextField(titlepreParam); - add(titlepre); + add(new Label((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.person.titlepre").localize())); + ParameterModel titlepreParam = new StringParameter(TITLEPRE); + titlepreParam.addParameterListener(new StringInRangeValidationListener(0, 1000)); + TextField titlepre = new TextField(titlepreParam); + add(titlepre); - add(new Label((String)BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.person.titlepost").localize())); - ParameterModel titlepostParam = new StringParameter(TITLEPOST); - titlepostParam.addParameterListener( new StringInRangeValidationListener(0, 1000) ); - TextField titlepost = new TextField(titlepostParam); - add(titlepost); + add(new Label((String) BasetypesGlobalizationUtil.globalize("cms.basetypes.ui.person.titlepost").localize())); + ParameterModel titlepostParam = new StringParameter(TITLEPOST); + titlepostParam.addParameterListener(new StringInRangeValidationListener(0, 1000)); + TextField titlepost = new TextField(titlepostParam); + add(titlepost); } public void init(FormSectionEvent fse) { - FormData data = fse.getFormData(); + FormData data = fse.getFormData(); PageState state = fse.getPageState(); - Contact contact = (Contact)getItemSelectionModel().getSelectedObject(state); - - if(contact.getPerson() != null) { + Contact contact = (Contact) getItemSelectionModel().getSelectedObject(state); + + if (contact.getPerson() != null) { data.put(SURNAME, contact.getPerson().getSurname()); data.put(GIVENNAME, contact.getPerson().getGivenName()); data.put(TITLEPRE, contact.getPerson().getTitlePre()); @@ -113,29 +109,35 @@ public class ContactEditPersonPropertyForm extends BasicPageForm implements Form } public void submitted(FormSectionEvent fse) { - if (m_step != null && - getSaveCancelSection().getCancelButton().isSelected(fse.getPageState())) { - m_step.cancelStreamlinedCreation(fse.getPageState()); - } + if (m_step != null + && getSaveCancelSection().getCancelButton().isSelected(fse.getPageState())) { + m_step.cancelStreamlinedCreation(fse.getPageState()); + } } public void process(FormSectionEvent fse) { - FormData data = fse.getFormData(); + FormData data = fse.getFormData(); PageState state = fse.getPageState(); - Contact contact = (Contact)getItemSelectionModel().getSelectedObject(state); + Contact contact = (Contact) getItemSelectionModel().getSelectedObject(state); - if (contact.getPerson() != null && - getSaveCancelSection().getSaveButton().isSelected(fse.getPageState())) { - contact.getPerson().setSurname((String)data.get(SURNAME)); - contact.getPerson().setGivenName((String)data.get(GIVENNAME)); - contact.getPerson().setTitlePre((String)data.get(TITLEPRE)); - contact.getPerson().setTitlePost((String)data.get(TITLEPOST)); - - contact.getPerson().save(); - } - - if (m_step != null) { - m_step.maybeForwardToNextStep(fse.getPageState()); - } + if (getSaveCancelSection().getSaveButton().isSelected(fse.getPageState())) { + + if (contact.getPerson() == null) { + contact.setPerson(new Person()); + contact.getPerson().setName("Person for " + contact.getName() + "(" + contact.getID() + ")"); + contact.getPerson().setTitle("Person for " + contact.getName() + "(" + contact.getID() + ")"); + } + + contact.getPerson().setSurname((String) data.get(SURNAME)); + contact.getPerson().setGivenName((String) data.get(GIVENNAME)); + contact.getPerson().setTitlePre((String) data.get(TITLEPRE)); + contact.getPerson().setTitlePost((String) data.get(TITLEPOST)); + + contact.getPerson().save(); + } + + if (m_step != null) { + m_step.maybeForwardToNextStep(fse.getPageState()); + } } -} \ No newline at end of file +} diff --git a/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactPropertiesStep.java b/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactPropertiesStep.java index 94c16f3b3..e42a82025 100644 --- a/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactPropertiesStep.java +++ b/ccm-cms/src/com/arsdigita/cms/basetypes/ui/ContactPropertiesStep.java @@ -101,8 +101,8 @@ public class ContactPropertiesStep extends SimpleEditStep { /* The DisplayComponent for the Basic Properties */ DomainObjectPropertySheet sheet = new DomainObjectPropertySheet(itemModel); - sheet.add(GlobalizationUtil.globalize("cms.basetypes.ui.name"), "name"); - sheet.add(GlobalizationUtil.globalize("cms.basetypes.ui.title"), "title"); + sheet.add(GlobalizationUtil.globalize("cms.contenttypes.ui.name"), "name"); + sheet.add(GlobalizationUtil.globalize("cms.contenttypes.ui.title"), "title"); if (!ContentSection.getConfig().getHideLaunchDate()) { sheet.add(GlobalizationUtil.globalize("cms.ui.authoring.page_launch_date"), ContentPage.LAUNCH_DATE, new DomainObjectPropertySheet.AttributeFormatter() { diff --git a/ccm-cms/src/com/arsdigita/cms/contenttypes/AbstractContentTypeLoader.java b/ccm-cms/src/com/arsdigita/cms/contenttypes/AbstractContentTypeLoader.java index c7bf0dda1..fd0832187 100755 --- a/ccm-cms/src/com/arsdigita/cms/contenttypes/AbstractContentTypeLoader.java +++ b/ccm-cms/src/com/arsdigita/cms/contenttypes/AbstractContentTypeLoader.java @@ -20,6 +20,7 @@ package com.arsdigita.cms.contenttypes; import com.arsdigita.cms.ContentSection; import com.arsdigita.cms.ContentType; +import com.arsdigita.cms.ContentTypeCollection; import com.arsdigita.cms.ContentTypeLifecycleDefinition; import com.arsdigita.cms.ContentTypeWorkflowTemplate; import com.arsdigita.cms.Template; @@ -44,10 +45,12 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.math.BigDecimal; import java.util.Date; import java.util.Iterator; import java.util.List; +import java.util.StringTokenizer; /** * This is the base loader that can be used by individual content types. @@ -57,11 +60,11 @@ import java.util.List; * @author Rafael H. Schloming <rhs@mit.edu> * @version $Revision: #754 $ $Date: 2005/09/02 $ $Author: sskracic $ **/ - public abstract class AbstractContentTypeLoader extends PackageLoader { public void run(final ScriptContext ctx) { new KernelExcursion() { + protected void excurse() { setEffectiveParty(Kernel.getSystemParty()); createTypes(ctx); @@ -81,12 +84,13 @@ public abstract class AbstractContentTypeLoader extends PackageLoader { DataCollection sections = ssn.retrieve(ContentSection.BASE_DATA_OBJECT_TYPE); while (sections.next()) { - ContentSection section = (ContentSection) - DomainObjectFactory.newInstance(sections.getDataObject()); - if ( !isLoadableInto(section) ) { continue; } + ContentSection section = (ContentSection) DomainObjectFactory.newInstance(sections.getDataObject()); + if (!isLoadableInto(section)) { + continue; + } LifecycleDefinitionCollection ldc = - section.getLifecycleDefinitions(); + section.getLifecycleDefinitions(); LifecycleDefinition ld = null; if (ldc.next()) { ld = ldc.getLifecycleDefinition(); @@ -100,9 +104,12 @@ public abstract class AbstractContentTypeLoader extends PackageLoader { tc.close(); } - for (Iterator it = types.iterator(); it.hasNext(); ) { + for (Iterator it = types.iterator(); it.hasNext();) { final ContentType type = (ContentType) it.next(); + // Save the ancestors for this content type + createPedigree(type); + section.addContentType(type); prepareSection(section, type, ld, wf); @@ -111,26 +118,26 @@ public abstract class AbstractContentTypeLoader extends PackageLoader { } protected void prepareSection(final ContentSection section, - final ContentType type, - final LifecycleDefinition ld, - final WorkflowTemplate wf) { - ContentTypeLifecycleDefinition.updateLifecycleDefinition - (section, type, ld); + final ContentType type, + final LifecycleDefinition ld, + final WorkflowTemplate wf) { + ContentTypeLifecycleDefinition.updateLifecycleDefinition(section, type, ld); - ContentTypeWorkflowTemplate.updateWorkflowTemplate - (section, type, wf); + ContentTypeWorkflowTemplate.updateWorkflowTemplate(section, type, wf); } protected abstract String[] getTypes(); private boolean isLoadableInto(ContentSection section) { - if ( section == null ) { throw new NullPointerException("section"); } + if (section == null) { + throw new NullPointerException("section"); + } - if ( getContentSections().size() > 0 ) { + if (getContentSections().size() > 0) { return getContentSections().contains(section.getName()); } else { return ContentSection.getConfig().getDefaultContentSection(). - equals(section.getName()); + equals(section.getName()); } } @@ -150,19 +157,18 @@ public abstract class AbstractContentTypeLoader extends PackageLoader { return java.util.Collections.EMPTY_LIST; } - /** * This provides an easy way to subtypes to register default * templates during the loading. When this is used, it should * be called by the loader class by overriding prepareSection */ protected Template setDefaultTemplate(final String name, - final String label, - final InputStream templateIs, - final ContentSection section, - final ContentType type, - final LifecycleDefinition ld, - final WorkflowTemplate wf) { + final String label, + final InputStream templateIs, + final ContentSection section, + final ContentType type, + final LifecycleDefinition ld, + final WorkflowTemplate wf) { final Template template = new Template(); template.setName(name); template.setLabel(label); @@ -170,12 +176,11 @@ public abstract class AbstractContentTypeLoader extends PackageLoader { template.setParent(section.getTemplatesFolder()); Assert.isTrue(templateIs != null, "Template not found"); - - final BufferedReader input = new BufferedReader - (new InputStreamReader(templateIs)); - + + final BufferedReader input = new BufferedReader(new InputStreamReader(templateIs)); + final StringBuffer body = new StringBuffer(); - + try { String line; @@ -184,16 +189,84 @@ public abstract class AbstractContentTypeLoader extends PackageLoader { body.append("\n"); } } catch (IOException ioe) { - throw new UncheckedWrapperException - ("Template cannot be read", ioe); + throw new UncheckedWrapperException("Template cannot be read", ioe); } template.setText(body.toString()); - TemplateManagerFactory.getInstance().addTemplate - (section, type, template, TemplateManager.PUBLIC_CONTEXT); + TemplateManagerFactory.getInstance().addTemplate(section, type, template, TemplateManager.PUBLIC_CONTEXT); template.publish(ld, new Date()); return template; } + + /** + * Generates the pedigree for this content type + * @param type The new content type + */ + private void createPedigree(ContentType type) { + + // The parent content type + ContentType parent = null; + + // Get all content types + ContentTypeCollection cts = ContentType.getAllContentTypes(); + + // This is a brute force method, but I can't come up with something + // better atm without changing either all Loader or the xml-files. + while (cts.next()) { + ContentType ct = cts.getContentType(); + + try { + Class.forName(type.getClassName()).asSubclass(Class.forName(ct.getClassName())); + } catch (Exception ex) { + // This cast is not valid so type is not a sublacss of ct + continue; + } + + // Save the current ct as possible parent if we haven't found any parent yet + // or if the current ancestor list is longer than that one from the possible + // parent earlier found + if (parent == null + || (parent.getAncestors() != null + && ct.getAncestors() != null + && parent.getAncestors().length() < ct.getAncestors().length())) { + parent = ct; + } + } + + // If there is a valid parent content type create the pedigree + if (parent != null && !parent.getClassName().equals(type.getClassName())) { + if (parent.getAncestors() != null) { + String parentAncestors = parent.getAncestors(); + + StringTokenizer strTok = new StringTokenizer(parentAncestors, "/"); + + // Add parent ancestors to this content types ancestor list + // Also while we iterate through the list, we also need to add + // this content type as sibling to all entries in the ancestor list + while (strTok.hasMoreElements()) { + + BigDecimal ctID = (BigDecimal) strTok.nextElement(); + + // Get the current content type + try { + ContentType ct = new ContentType(ctID); + ct.addSiblings(ctID); + } catch (Exception ex) { + // The db is broken. There is no content type for this ID + } + + // Add parent ancestor + type.addAncestor(ctID); + } + } + + // Add parent to ancestor list + type.addAncestor(parent.getID()); + + // Add this to parent siblings + parent.addSiblings(type.getID()); + } + } } diff --git a/ccm-cms/src/com/arsdigita/cms/enterprise.init b/ccm-cms/src/com/arsdigita/cms/enterprise.init index 883cf6af7..2e5547336 100755 --- a/ccm-cms/src/com/arsdigita/cms/enterprise.init +++ b/ccm-cms/src/com/arsdigita/cms/enterprise.init @@ -11,6 +11,10 @@ init com.arsdigita.cms.installer.Initializer { init com.arsdigita.cms.installer.xml.ContentTypeInitializer { contentTypes = { + "/WEB-INF/basetypes/Address.xml", + "/WEB-INF/basetypes/Article.xml", + "/WEB-INF/basetypes/Contact.xml", + "/WEB-INF/basetypes/Person.xml", "/WEB-INF/content-types/Template.xml" }; } diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchFolderBrowser.java b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchFolderBrowser.java index 571097cb2..294de21c5 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchFolderBrowser.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchFolderBrowser.java @@ -18,7 +18,6 @@ */ package com.arsdigita.cms.ui; - import com.arsdigita.bebop.Bebop; import com.arsdigita.bebop.Component; import com.arsdigita.bebop.Label; @@ -52,10 +51,14 @@ import com.arsdigita.cms.dispatcher.Utilities; import com.arsdigita.cms.ui.folder.FolderManipulator; import com.arsdigita.cms.ui.folder.FolderSelectionModel; import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.persistence.CompoundFilter; +import com.arsdigita.persistence.FilterFactory; import com.arsdigita.util.Assert; import java.math.BigDecimal; - +import java.util.HashSet; +import java.util.Iterator; +import java.util.StringTokenizer; /** * Browse folders and items. If the user clicks on a folder, the folder @@ -67,42 +70,34 @@ import java.math.BigDecimal; */ public class ItemSearchFolderBrowser extends Table { - private static final org.apache.log4j.Logger s_log = - org.apache.log4j.Logger.getLogger(ItemSearchFolderBrowser.class); - + private static final org.apache.log4j.Logger s_log = + org.apache.log4j.Logger.getLogger(ItemSearchFolderBrowser.class); public static final int MAX_ROWS = 15; - private static GlobalizedMessage[] s_headers = { globalize("cms.ui.folder.name"), globalize("cms.ui.folder.title"), - globalize("cms.ui.folder.type") }; - + globalize("cms.ui.folder.type")}; private FolderSelectionModel m_currentFolder; - private TableActionListener m_folderChanger; - private TableActionListener m_deleter; - private TableActionListener m_indexChanger; - private TableColumn m_nameColumn; - private Paginator m_paginator; public ItemSearchFolderBrowser(FolderSelectionModel currentFolder) { - super((FolderTableModelBuilder)null, s_headers); + super((FolderTableModelBuilder) null, s_headers); FolderTableModelBuilder builder = new FolderTableModelBuilder(); - setModelBuilder( builder ); + setModelBuilder(builder); - m_paginator = new Paginator( builder, MAX_ROWS ); + m_paginator = new Paginator(builder, MAX_ROWS); m_currentFolder = currentFolder; setClassAttr("dataTable"); getHeader().setDefaultRenderer( - new com.arsdigita.cms.ui.util.DefaultTableCellRenderer()); + new com.arsdigita.cms.ui.util.DefaultTableCellRenderer()); m_nameColumn = getColumn(0); m_nameColumn.setCellRenderer(new NameCellRenderer()); @@ -111,60 +106,66 @@ public class ItemSearchFolderBrowser extends Table { setEmptyView(new Label(globalize("cms.ui.folder.no_items"))); - Assert.exists( m_currentFolder.getStateParameter() ); + Assert.exists(m_currentFolder.getStateParameter()); } public Paginator getPaginator() { return m_paginator; } + @Override public void register(Page p) { super.register(p); p.addComponentStateParam(this, m_currentFolder.getStateParameter()); p.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent event) { - // MP: This action listener should only be called when the - // folder browser is visible. - showHideFolderActions(event.getPageState()); - } - }); + + public void actionPerformed(ActionEvent event) { + // MP: This action listener should only be called when the + // folder browser is visible. + showHideFolderActions(event.getPageState()); + } + }); } - private Folder getCurrentFolder( PageState state ) { - return (Folder) m_currentFolder.getSelectedObject( state ); + private Folder getCurrentFolder(PageState state) { + return (Folder) m_currentFolder.getSelectedObject(state); } private void showHideFolderActions(PageState state) { SecurityManager sm = Utilities.getSecurityManager(state); - Folder folder = getCurrentFolder( state ); + Folder folder = getCurrentFolder(state); Assert.exists(folder); } - public FolderSelectionModel getFolderSelectionModel() { return m_currentFolder; } private class FolderTableModelBuilder - extends AbstractTableModelBuilder implements PaginationModelBuilder { + extends AbstractTableModelBuilder implements PaginationModelBuilder { private RequestLocal m_size = new RequestLocal() { - protected Object initialValue( PageState state ) { - Folder.ItemCollection itemColl = getItemCollection( state ); - if( null == itemColl ) return new Integer( 0 ); - return new Integer( (int) itemColl.size() ); + @Override + protected Object initialValue(PageState state) { + Folder.ItemCollection itemColl = getItemCollection(state); + + if (null == itemColl) { + return new Integer(0); + } + return new Integer((int) itemColl.size()); } }; - private RequestLocal m_itemColl = new RequestLocal() { - protected Object initialValue( PageState state ) { - Folder.ItemCollection itemColl = getItemCollection( state ); + + @Override + protected Object initialValue(PageState state) { + Folder.ItemCollection itemColl = getItemCollection(state); itemColl.addOrder("item.name"); itemColl.setRange(new Integer(m_paginator.getFirst(state)), - new Integer(m_paginator.getLast(state) + 1)); + new Integer(m_paginator.getLast(state) + 1)); return itemColl; } @@ -172,17 +173,17 @@ public class ItemSearchFolderBrowser extends Table { public TableModel makeModel(Table t, PageState s) { FolderSelectionModel sel = ((ItemSearchFolderBrowser) t).getFolderSelectionModel(); - Folder f = getCurrentFolder( s ); + Folder f = getCurrentFolder(s); - if( s_log.isDebugEnabled() ) { - if( null == f ) - s_log.debug( "Selected folder is null" ); - else - s_log.debug( "Selected folder: " + f.getLabel() + " " + - f.getOID().toString() ); + if (s_log.isDebugEnabled()) { + if (null == f) { + s_log.debug("Selected folder is null"); + } else { + s_log.debug("Selected folder: " + f.getLabel() + " " + f.getOID().toString()); + } } - if ( f == null ) { + if (f == null) { return Table.EMPTY_MODEL; } else { t.getRowSelectionModel().clearSelection(s); @@ -190,23 +191,46 @@ public class ItemSearchFolderBrowser extends Table { } } - private Folder.ItemCollection getItemCollection( PageState state ) { - Folder f = getCurrentFolder( state ); + private Folder.ItemCollection getItemCollection(PageState state) { + Folder f = getCurrentFolder(state); Folder.ItemCollection itemColl = f.getPrimaryInstances(); - if( null == itemColl ) return null; + if (null == itemColl) { + return null; + } BigDecimal singleTypeID = - (BigDecimal) state.getValue (new BigDecimalParameter - (ItemSearch.SINGLE_TYPE_PARAM)); - - if (singleTypeID != null) - itemColl.addEqualsFilter (ContentItem.CONTENT_TYPE + - "." + ContentType.ID, singleTypeID); + (BigDecimal) state.getValue(new BigDecimalParameter(ItemSearch.SINGLE_TYPE_PARAM)); + + if (singleTypeID != null) { + + // The Filter Factory + FilterFactory ff = itemColl.getFilterFactory(); + + // Create an or-filter + CompoundFilter or = ff.or(); + + // The content type must be either of the requested type + or.addFilter(ff.equals(ContentItem.CONTENT_TYPE + "." + ContentType.ID, singleTypeID)); + + // Or must be a sibling of the requested type + try { + ContentType ct = new ContentType(singleTypeID); + + StringTokenizer strTok = new StringTokenizer(ct.getSiblings(), "/"); + while (strTok.hasMoreElements()) { + or.addFilter(ff.equals(ContentItem.CONTENT_TYPE + "." + ContentType.ID, (String) strTok.nextElement())); + } + } catch (Exception ex) { + // WTF? The selected content type does not exist in the table??? + } + + itemColl.addFilter(or); + } itemColl.addOrder("isFolder desc"); - itemColl.addOrder("lower(item." + - ContentItem.NAME + ") "); + itemColl.addOrder("lower(item." + + ContentItem.NAME + ") "); return itemColl; } @@ -225,10 +249,10 @@ public class ItemSearchFolderBrowser extends Table { * than 1 page of items, false otherwise */ public boolean isVisible(PageState state) { - int size = ((Integer) m_size.get( state )).intValue(); - - return ItemSearchFolderBrowser.this.isVisible(state) && - ( size > MAX_ROWS ); + int size = ((Integer) m_size.get(state)).intValue(); + + return ItemSearchFolderBrowser.this.isVisible(state) + && (size > MAX_ROWS); } } @@ -236,90 +260,83 @@ public class ItemSearchFolderBrowser extends Table { * Produce links to view an item or control links for folders * to change into the folder. */ - private class NameCellRenderer extends DefaultTableCellRenderer - { - public NameCellRenderer() - { + private class NameCellRenderer extends DefaultTableCellRenderer { + + public NameCellRenderer() { super(true); } - public Component getComponent (Table table, PageState state, - Object value, boolean isSelected, - Object key, int row, int column) - { + @Override + public Component getComponent(Table table, PageState state, + Object value, boolean isSelected, + Object key, int row, int column) { Folder.ItemCollection coll = (Folder.ItemCollection) value; String name = coll.getName(); - if ( coll.isFolder() ) - return super.getComponent(table, state, name, - isSelected, key, row, column); - else - { - ContentSection section = CMS.getContext().getContentSection(); - BigDecimal id = (BigDecimal) key; + if (coll.isFolder()) { + return super.getComponent(table, state, name, isSelected, key, row, column); + } else { + ContentSection section = CMS.getContext().getContentSection(); + BigDecimal id = (BigDecimal) key; - if (section == null) - return new Label (name); - else - { - //ItemResolver resolver = section.getItemResolver(); + if (section == null) { + return new Label(name); + } else { + //ItemResolver resolver = section.getItemResolver(); - //String url = - //resolver.generateItemURL - //(state, id, name, section, coll.getVersion())); + //String url = + //resolver.generateItemURL + //(state, id, name, section, coll.getVersion())); - SimpleContainer container = new SimpleContainer (); + SimpleContainer container = new SimpleContainer(); - String widget = - (String) state.getValue (new StringParameter - (ItemSearchPopup.WIDGET_PARAM)); - boolean useURL = "true".equals - (state.getValue(new StringParameter(ItemSearchPopup.URL_PARAM))); + String widget = + (String) state.getValue(new StringParameter(ItemSearchPopup.WIDGET_PARAM)); + boolean useURL = "true".equals(state.getValue(new StringParameter(ItemSearchPopup.URL_PARAM))); - String fillString = useURL ? - ItemSearchPopup.getItemURL(state.getRequest(), - coll.getDomainObject().getOID()) : - id + - " (" + name + ")"; - - Label js = new Label (generateJSLabel (id, widget, - fillString), - false); - container.add (js); + String fillString = useURL + ? ItemSearchPopup.getItemURL(state.getRequest(), + coll.getDomainObject().getOID()) + : id + + " (" + name + ")"; - String url = "#"; + Label js = new Label(generateJSLabel(id, widget, + fillString), + false); + container.add(js); - Link link = new Link (name, url); - link.setClassAttr ("title"); - link.setOnClick ("return fillItem" + id + "()"); + String url = "#"; - container.add (link); + Link link = new Link(name, url); + link.setClassAttr("title"); + link.setOnClick("return fillItem" + id + "()"); - return container; - } + container.add(link); + + return container; } + } } - private String generateJSLabel(BigDecimal id, String widget, String fill) - { - StringBuffer buffer = new StringBuffer(); - buffer.append(" "); - + private String generateJSLabel(BigDecimal id, String widget, String fill) { + StringBuffer buffer = new StringBuffer(); + buffer.append(" "); + return buffer.toString(); } } @@ -327,33 +344,27 @@ public class ItemSearchFolderBrowser extends Table { /** * Table model around ItemCollection */ - private static class FolderTableModel implements TableModel - { + private static class FolderTableModel implements TableModel { + private static final int NAME = 0; private static final int TITLE = 1; private static final int TYPE = 2; - private Folder.ItemCollection m_itemColl; - public FolderTableModel(Folder.ItemCollection itemColl) - { + public FolderTableModel(Folder.ItemCollection itemColl) { m_itemColl = itemColl; } - public int getColumnCount() - { + public int getColumnCount() { return 3; } - public boolean nextRow() - { + public boolean nextRow() { return m_itemColl != null ? m_itemColl.next() : false; } - public Object getElementAt(int columnIndex) - { - switch (columnIndex) - { + public Object getElementAt(int columnIndex) { + switch (columnIndex) { case NAME: return m_itemColl; case TITLE: @@ -361,30 +372,29 @@ public class ItemSearchFolderBrowser extends Table { case TYPE: return m_itemColl.getTypeLabel(); default: - throw new - IndexOutOfBoundsException ("Column index " + columnIndex + - " not in table model."); - } + throw new IndexOutOfBoundsException("Column index " + columnIndex + + " not in table model."); + } } - public Object getKeyAt(int columnIndex) - { + public Object getKeyAt(int columnIndex) { // Mark folders by using their negative ID (dirty, dirty) - return ( m_itemColl.isFolder() ) ? m_itemColl.getID().negate() - : m_itemColl.getID(); + return (m_itemColl.isFolder()) ? m_itemColl.getID().negate() + : m_itemColl.getID(); } } private class FolderChanger extends TableActionAdapter { + public void cellSelected(TableActionEvent e) { PageState s = e.getPageState(); int col = e.getColumn().intValue(); - if ( m_nameColumn != getColumn(col) ) { + if (m_nameColumn != getColumn(col)) { return; } String key = (String) e.getRowKey(); - if ( key.startsWith("-") ) { + if (key.startsWith("-")) { clearSelection(s); getFolderSelectionModel().setSelectedKey(s, key.substring(1)); m_paginator.reset(s); @@ -401,5 +411,4 @@ public class ItemSearchFolderBrowser extends Table { private static GlobalizedMessage globalize(String key) { return FolderManipulator.globalize(key); } - } diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchParameter.java b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchParameter.java index 557f27de9..f2775b455 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchParameter.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchParameter.java @@ -78,6 +78,7 @@ public class ItemSearchParameter extends StringParameter { * @throws IllegalArgumentException if the request parameter does not * look like a valid email address. */ + @Override public Object transformValue(HttpServletRequest request) throws IllegalArgumentException { @@ -86,6 +87,7 @@ public class ItemSearchParameter extends StringParameter { return unmarshal(itemStr); } + @Override public Object unmarshal(String encoded) throws IllegalArgumentException { @@ -113,16 +115,13 @@ public class ItemSearchParameter extends StringParameter { } if (m_contentType != null && - !contentItem.getContentType().equals(m_contentType)) { + !contentItem.isContentType(m_contentType)) { return null; - /* - throw new IllegalArgumentException - (encoded + " is not a valid " + m_contentType.getLabel()); - */ } return contentItem; } + @Override public String marshal(Object value) { if (value == null) { return null; @@ -132,6 +131,7 @@ public class ItemSearchParameter extends StringParameter { } } + @Override public Class getValueClass() { return ContentPage.class; } diff --git a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchWidget.java b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchWidget.java index ca092dc30..3c182441e 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchWidget.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/ItemSearchWidget.java @@ -44,35 +44,32 @@ import com.arsdigita.web.ParameterMap; import com.arsdigita.web.URL; import org.apache.log4j.Logger; - /** * A class representing a content item search field in an HTML form. * * @author Scott Seago (sseago@redhat.com) * @version $Id: ItemSearchWidget.java 1166 2006-06-14 11:45:15Z fabrice $ */ -public class ItemSearchWidget extends FormSection - implements BebopConstants, FormSubmissionListener, FormInitListener { +public class ItemSearchWidget extends FormSection + implements BebopConstants, FormSubmissionListener, FormInitListener { private static final Logger s_log = Logger.getLogger(ItemSearchWidget.class); private TextField m_item; private Submit m_search; private Submit m_clear; - private Label m_jsLabel; - private Label m_topHR; - private Label m_bottomHR; + private Label m_jsLabel; + private Label m_topHR; + private Label m_bottomHR; private ContentType m_contentType; private ItemSearchSectionInline m_searchComponent; - private String m_name; private String m_searchName; private String m_clearName; private ParameterModel m_model; - public static final String BEBOP_ITEM_SEARCH = "bebop:itemSearch"; - + private class ItemFragment extends TextField { - + private ItemSearchWidget parent; public ItemFragment(ParameterModel parameter, ItemSearchWidget parent) { @@ -82,31 +79,31 @@ public class ItemSearchWidget extends FormSection this.setSize(35); } } + private class SearchFragment extends Submit { - + private ItemSearchWidget parent; private ContentType contentType; - public SearchFragment(String name, - ItemSearchWidget parent, - ContentType contentType) { + public SearchFragment(String name, + ItemSearchWidget parent, + ContentType contentType) { super(name, "Search"); this.parent = parent; this.contentType = contentType; - this.setAttribute("onClick", "return " + parent.m_item.getName().replace('.','_') + "Popup(this.form)"); + this.setAttribute("onClick", "return " + parent.m_item.getName().replace('.', '_') + "Popup(this.form)"); this.setAttribute("value", "Search"); } public boolean isVisible(PageState ps) { - return (!(parent.m_search.isSelected(ps) || - parent.m_searchComponent.hasQuery(ps)) && - super.isVisible(ps)); + return (!(parent.m_search.isSelected(ps) + || parent.m_searchComponent.hasQuery(ps)) + && super.isVisible(ps)); } - } private class ClearFragment extends Submit { - + private ItemSearchWidget parent; public ClearFragment(String name, ItemSearchWidget parent) { @@ -118,18 +115,17 @@ public class ItemSearchWidget extends FormSection } private class LabelFragment extends Label { - + private ItemSearchWidget parent; public LabelFragment(String name, boolean escaping, ItemSearchWidget parent) { super(name, escaping); this.parent = parent; } - } private class ItemSearchFragment extends ItemSearchSectionInline { - + private ItemSearchWidget parent; public ItemSearchFragment(String name, String context, ItemSearchWidget parent) { @@ -139,52 +135,51 @@ public class ItemSearchWidget extends FormSection @Override public boolean isVisible(PageState ps) { - return ((m_search.isSelected(ps) || - hasQuery(ps)) && - super.isVisible(ps)); + return ((m_search.isSelected(ps) + || hasQuery(ps)) + && super.isVisible(ps)); } - } private class HRLabel extends Label { - + public HRLabel() { super("
", false); } @Override public boolean isVisible(PageState ps) { - return ((m_search.isSelected(ps) || - m_searchComponent.hasQuery(ps)) && - super.isVisible(ps)); + return ((m_search.isSelected(ps) + || m_searchComponent.hasQuery(ps)) + && super.isVisible(ps)); } - } + /** * Construct a new ItemSearchWidget. The model must be an ItemSearchParameter */ public ItemSearchWidget(ParameterModel model) { - this(model,null); + this(model, null); } /** * Construct a new ItemSearchWidget. The model must be an ItemSearchParameter */ public ItemSearchWidget(ParameterModel model, - ContentType contentType) { + ContentType contentType) { super(new BoxPanel(BoxPanel.VERTICAL)); - if ( ! (model instanceof ItemSearchParameter)) { + if (!(model instanceof ItemSearchParameter)) { throw new IllegalArgumentException( - "The ItemSearch widget " + model.getName() + - " must be backed by a ItemSearchParameter parmeter model"); + "The ItemSearch widget " + model.getName() + + " must be backed by a ItemSearchParameter parmeter model"); } m_name = model.getName(); m_searchName = m_name + "_search"; m_clearName = m_name + "_clear"; m_model = model; - + final String typeURLFrag; if (contentType != null) { typeURLFrag = contentType.getID().toString(); @@ -196,44 +191,45 @@ public class ItemSearchWidget extends FormSection m_item = new ItemFragment(model, this); m_search = new SearchFragment(m_searchName, this, m_contentType); m_clear = new ClearFragment(m_clearName, this); - m_jsLabel = new LabelFragment("",false, this); - m_jsLabel.addPrintListener( new PrintListener() { - public void prepare(PrintEvent event) { - PageState state = event.getPageState(); - Label t = (Label) event.getTarget(); - String formName = ((LabelFragment) t).parent.getSearchButton().getForm().getName(); - ParameterMap params = new ParameterMap(); - params.setParameter ("section_id", - CMS.getContext().getContentSection().getID()); - params.setParameter("widget", formName + ".elements['" + m_item.getName() + "']"); - if (typeURLFrag != null) { - params.setParameter("single_type", typeURLFrag); - } + m_jsLabel = new LabelFragment("", false, this); + m_jsLabel.addPrintListener(new PrintListener() { - - String searchURL = ContentCenterDispatcher.getURLStubForClass( + public void prepare(PrintEvent event) { + PageState state = event.getPageState(); + Label t = (Label) event.getTarget(); + String formName = ((LabelFragment) t).parent.getSearchButton().getForm().getName(); + ParameterMap params = new ParameterMap(); + params.setParameter("section_id", + CMS.getContext().getContentSection().getID()); + params.setParameter("widget", formName + ".elements['" + m_item.getName() + "']"); + if (typeURLFrag != null) { + params.setParameter("single_type", typeURLFrag); + } + + + String searchURL = ContentCenterDispatcher.getURLStubForClass( ItemSearchPage.class.getName()); - s_log.debug("Search URL stub is: " + searchURL); + s_log.debug("Search URL stub is: " + searchURL); - searchURL = com.arsdigita.cms.dispatcher.Utilities.getWorkspaceURL() + searchURL = com.arsdigita.cms.dispatcher.Utilities.getWorkspaceURL() + searchURL; - // TODO Not sure what to do when you get a null here + // TODO Not sure what to do when you get a null here - URL url = URL.there(state.getRequest(), searchURL,params); - - t.setLabel(" "); - } - }); + URL url = URL.there(state.getRequest(), searchURL, params); + + t.setLabel(" "); + } + }); m_topHR = new HRLabel(); add(m_topHR); FormSection searchSection = new FormSection(new BoxPanel(BoxPanel.HORIZONTAL)); @@ -250,7 +246,8 @@ public class ItemSearchWidget extends FormSection add(m_bottomHR); } - + + @Override public void register(Page p) { super.register(p); p.setVisibleDefault(m_topHR, false); @@ -261,24 +258,28 @@ public class ItemSearchWidget extends FormSection public ItemSearchWidget(String name) { this(new ItemSearchParameter(name)); } + public ItemSearchWidget(String name, - String objectType) - throws DataObjectNotFoundException { - this(name, (objectType == null || objectType.length()==0 ? - null : - ContentType.findByAssociatedObjectType(objectType))); + String objectType) + throws DataObjectNotFoundException { + this(name, (objectType == null || objectType.length() == 0 + ? null + : ContentType.findByAssociatedObjectType(objectType))); } + public ItemSearchWidget(String name, - ContentType contentType) { + ContentType contentType) { this(new ItemSearchParameter(name, contentType), contentType); } public Submit getSearchButton() { return m_search; } + public Submit getClearButton() { return m_clear; } + public TextField getItemField() { return m_item; } @@ -315,7 +316,7 @@ public class ItemSearchWidget extends FormSection } throw new FormProcessException("item search FormSection submit"); - + } else if (m_searchComponent.hasQuery(s)) { s_log.debug("Has query"); try { @@ -354,7 +355,7 @@ public class ItemSearchWidget extends FormSection throw new FormProcessException("item search FormSection submit"); } else if (m_clear.isSelected(s)) { s_log.debug("Clear selected"); - m_item.setValue(s,null); + m_item.setValue(s, null); try { m_searchComponent.setVisible(s, false); m_topHR.setVisible(s, false); @@ -376,5 +377,4 @@ public class ItemSearchWidget extends FormSection } } } - }