diff --git a/ccm-cms/src/com/arsdigita/cms/AssociationCopier.java b/ccm-cms/src/com/arsdigita/cms/AssociationCopier.java index 8dd5fc630..8a432bc4b 100644 --- a/ccm-cms/src/com/arsdigita/cms/AssociationCopier.java +++ b/ccm-cms/src/com/arsdigita/cms/AssociationCopier.java @@ -1,6 +1,5 @@ package com.arsdigita.cms; -import com.arsdigita.domain.DomainObject; import com.arsdigita.persistence.metadata.Property; /** @@ -9,12 +8,30 @@ import com.arsdigita.persistence.metadata.Property; * @version $Id$ */ public interface AssociationCopier { - - boolean copyReverseProperty(CustomCopy source, - DomainObject target, - Property property, - DomainObject value, - ItemCopier copier); - - + + /** + *

+ * Return the property which is handled by this implementation. Format: + *

+ *

+ * {@code $type::$property} + *

+ *

+ * Where {@code $type} is the fully qualified name of the class/type owing + * the property and {@code property} is the name the property. Example + *

+ *

+ * {@code com.arsdigita.cms.contenttypes.GenericPerson::publications} + *

+ *

+ * This indicates that the implementation handles a property + * {@code publications} added to the {@code GenericPerson} type by some + * module via an PDL association. + *

+ * + * @return + */ + String forProperty(); + + boolean copyProperty(CustomCopy source, Property property, ItemCopier copier); } diff --git a/ccm-cms/src/com/arsdigita/cms/AssociationCopierLoader.java b/ccm-cms/src/com/arsdigita/cms/AssociationCopierLoader.java new file mode 100644 index 000000000..8c9297cb1 --- /dev/null +++ b/ccm-cms/src/com/arsdigita/cms/AssociationCopierLoader.java @@ -0,0 +1,77 @@ +package com.arsdigita.cms; + +import com.arsdigita.persistence.metadata.Property; +import java.util.HashMap; +import java.util.Map; +import org.apache.log4j.Logger; + +/** + * + * @author Jens Pelzetter + * @version $Id$ + */ +public final class AssociationCopierLoader { + + private static final AssociationCopierLoader INSTANCE = + new AssociationCopierLoader(); + private static final Logger logger = + Logger.getLogger(AssociationCopierLoader.class); + private Map copiers = + new HashMap(); + + private AssociationCopierLoader() { + final String[] assocCopierNames = CMSConfig.getInstance(). + getAssocCopiers(); + + for (String assocCopierName : assocCopierNames) { + loadAssocCopier(assocCopierName); + } + } + + private void loadAssocCopier(final String name) { + final Class clazz; + try { + clazz = Class.forName(name); + } catch (ClassNotFoundException ex) { + logger.warn(String.format("No class found for name '%s'. Skiping.", + name), + ex); + return; + } + + if (clazz.isAssignableFrom(AssociationCopier.class)) { + try { + final AssociationCopier copier = (AssociationCopier) clazz. + newInstance(); + + copiers.put(copier.forProperty(), copier); + } catch (InstantiationException ex) { + logger.warn(String.format( + "Failed to instaniate copier '%s'. Skiping.", + name), + ex); + } catch (IllegalAccessException ex) { + logger.warn(String.format( + "Failed to instaniate copier '%s'. Skiping.", + name), + ex); + } + } else { + logger.warn(String.format("Class '%s' is not an implementation of " + + "the AssociationCopier interface. " + + "Skiping", + name)); + } + } + + public static AssociationCopierLoader getInstance() { + return INSTANCE; + } + + public AssociationCopier getAssociationCopierFor(final Property property, + final CustomCopy source) { + return copiers.get(String.format("%s::%s", + source.getClass().getName(), + property.getName())); + } +} diff --git a/ccm-cms/src/com/arsdigita/cms/CMSConfig.java b/ccm-cms/src/com/arsdigita/cms/CMSConfig.java index 86bca438d..249eee156 100755 --- a/ccm-cms/src/com/arsdigita/cms/CMSConfig.java +++ b/ccm-cms/src/com/arsdigita/cms/CMSConfig.java @@ -620,6 +620,14 @@ public final class CMSConfig extends AbstractConfig { "com.arsdigita.cms.lifecycle.threaded_publishing", Parameter.REQUIRED, true); + + /** + * Copiers for associations not known yet. For example for associations + * with the generic types defined in this module from another module. + */ + private final Parameter m_assocCopiers = new StringArrayParameter("com.arsdigita.cms.publish.association_copiers", + Parameter.REQUIRED, + new String[]{}); // /////////////////////////////////////////// // publishToFile package related parameter @@ -704,6 +712,7 @@ public final class CMSConfig extends AbstractConfig { register(m_useOldStyleItemLifecycleItemPane); register(m_threadPublishing); + register(m_assocCopiers); // publishToFile package related parameter // Moved to publishToFile.PublishToFileConfig as of version 6.0.2 @@ -1122,4 +1131,8 @@ public final class CMSConfig extends AbstractConfig { public Boolean getThreadedPublishing() { return (Boolean) get(m_threadPublishing); } + + public String[] getAssocCopiers() { + return (String[]) get(m_assocCopiers); + } } diff --git a/ccm-cms/src/com/arsdigita/cms/ContentItem.java b/ccm-cms/src/com/arsdigita/cms/ContentItem.java index edaa44050..ae539b574 100755 --- a/ccm-cms/src/com/arsdigita/cms/ContentItem.java +++ b/ccm-cms/src/com/arsdigita/cms/ContentItem.java @@ -1139,7 +1139,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { s_log.debug("Deleting old live version"); oldVersion.delete(); - PublishedLink.refreshOnUnpublish(this); + PublishedLink.refreshOnUnpublish(this); } if (parent instanceof ContentBundle || parent instanceof Folder) { @@ -1167,7 +1167,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { save(); - PublishedLink.updateLiveLinks(version); + PublishedLink.updateLiveLinks(version); save(); // publish item (as template or html pages) to the file @@ -1947,6 +1947,14 @@ public class ContentItem extends VersionedACSObject implements CustomCopy { } } + final AssociationCopierLoader assocCopierLoader = + AssociationCopierLoader.getInstance(); + final AssociationCopier assocCopier = assocCopierLoader. + getAssociationCopierFor(property, source); + if (assocCopier != null) { + return assocCopier.copyProperty(source, property, copier); + } + return false; }