Versuch der Behebung der Probleme mit Sprachvarianten und Assoziationen

git-svn-id: https://svn.libreccm.org/ccm/trunk@973 8810af33-2d31-482b-a856-94f89814c4df
master
jensp 2011-06-20 14:00:03 +00:00
parent c3e8aa14b3
commit adc6fa293a
10 changed files with 426 additions and 158 deletions

View File

@ -203,10 +203,12 @@ import java.util.Set;
public class ContentItem extends VersionedACSObject implements CustomCopy { public class ContentItem extends VersionedACSObject implements CustomCopy {
private static final Logger s_log = Logger.getLogger(ContentItem.class); private static final Logger s_log = Logger.getLogger(ContentItem.class);
private static final Logger s_logDenorm = Logger.getLogger(ContentItem.class.getName() + ".Denorm"); private static final Logger s_logDenorm =
Logger.getLogger(ContentItem.class.getName()
+ ".Denorm");
private static final String MODEL = "com.arsdigita.cms"; private static final String MODEL = "com.arsdigita.cms";
private static final String QUERY_PENDING_ITEMS = private static final String QUERY_PENDING_ITEMS =
MODEL + ".getPendingSortedByLifecycle"; MODEL + ".getPendingSortedByLifecycle";
public static final String BASE_DATA_OBJECT_TYPE = MODEL + ".ContentItem"; public static final String BASE_DATA_OBJECT_TYPE = MODEL + ".ContentItem";
/** /**
* A state marking the draft or master item corresponding to a * A state marking the draft or master item corresponding to a
@ -234,7 +236,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
public static final String VERSIONS = "slaveVersions"; public static final String VERSIONS = "slaveVersions";
public static final String CONTENT_SECTION = "section"; public static final String CONTENT_SECTION = "section";
private static final String PUBLISH_LISTENER_CLASS = private static final String PUBLISH_LISTENER_CLASS =
PublishLifecycleListener.class.getName(); PublishLifecycleListener.class.getName();
private VersionCache m_pending; private VersionCache m_pending;
private VersionCache m_live; private VersionCache m_live;
private boolean m_wasNew; private boolean m_wasNew;
@ -302,19 +304,20 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
} }
} }
private static DomainObjectObserver s_parentObs = private static DomainObjectObserver s_parentObs =
new AbstractDomainObjectObserver() { new AbstractDomainObjectObserver() {
public void set(DomainObject dobj, String name, public void set(DomainObject dobj, String name,
Object old, Object newVal) { Object old, Object newVal) {
if (PARENT.equals(name)) { if (PARENT.equals(name)) {
ContentItem ci = (ContentItem) dobj; ContentItem ci = (ContentItem) dobj;
if (newVal != null) { if (newVal != null) {
PermissionService.setContext(ci.getOID(), ((DataObject) newVal).getOID()); PermissionService.setContext(ci.getOID(),
} ((DataObject) newVal).getOID());
}
} }
}; }
}
};
/** /**
* Called from the base class (<code>DomainObject</code>) * Called from the base class (<code>DomainObject</code>)
@ -341,7 +344,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
if (isNew()) { if (isNew()) {
s_log.debug(this + " is being newly created; " s_log.debug(this + " is being newly created; "
+ "marking it as a draft version"); + "marking it as a draft version");
m_wasNew = true; m_wasNew = true;
@ -351,7 +354,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
try { try {
final ContentType type = final ContentType type =
ContentType.findByAssociatedObjectType(getSpecificObjectType()); ContentType.findByAssociatedObjectType(
getSpecificObjectType());
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("Set content type for " + this + " to " + type); s_log.debug("Set content type for " + this + " to " + type);
@ -406,12 +410,12 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
* @param propertyName * @param propertyName
* @param dobj * @param dobj
* @return * @return
*/ */
@Override @Override
public DataObject add(String propertyName, DomainObject dobj) { public DataObject add(String propertyName, DomainObject dobj) {
return super.add(propertyName, dobj); return super.add(propertyName, dobj);
} }
/** /**
* Public remove for use by metadata forms * Public remove for use by metadata forms
* *
@ -422,11 +426,11 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
public void remove(String propertyName, DomainObject dobj) { public void remove(String propertyName, DomainObject dobj) {
super.remove(propertyName, dobj); super.remove(propertyName, dobj);
} }
/** /**
* For new content items, sets the associated content type if it * For new content items, sets the associated content type if it
* has not been already set. * has not been already set.
*/ */
@Override @Override
protected void beforeSave() { protected void beforeSave() {
m_wasNew = isNew(); m_wasNew = isNew();
@ -442,10 +446,10 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
} }
/* /*
removed cg - object observer sets context based removed cg - object observer sets context based
on parent whenever parent is updated on parent whenever parent is updated
protected void afterSave() { protected void afterSave() {
super.afterSave(); super.afterSave();
s_log.info("******After Save of object " + getOID()); s_log.info("******After Save of object " + getOID());
@ -478,11 +482,11 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
setContentSection(((ContentItem) parent).getContentSection()); setContentSection(((ContentItem) parent).getContentSection());
} else { } else {
s_log.debug("The item's parent is not a folder; I am " s_log.debug("The item's parent is not a folder; I am "
+ "not setting the default content section"); + "not setting the default content section");
} }
} else { } else {
s_log.debug("The item's version is null or it is not draft; " s_log.debug("The item's version is null or it is not draft; "
+ "doing nothing"); + "doing nothing");
} }
} }
@ -522,7 +526,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
* Get the parent object. * Get the parent object.
*/ */
public ACSObject getParent() { public ACSObject getParent() {
return (ACSObject) DomainObjectFactory.newInstance((DataObject) get(PARENT)); return (ACSObject) DomainObjectFactory.newInstance((DataObject) get(
PARENT));
} }
/** /**
@ -542,7 +547,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
*/ */
public final ItemCollection getChildren() { public final ItemCollection getChildren() {
final DataAssociationCursor cursor = final DataAssociationCursor cursor =
((DataAssociation) super.get(CHILDREN)).cursor(); ((DataAssociation) super.get(CHILDREN)).
cursor();
return new ItemCollection(cursor); return new ItemCollection(cursor);
} }
@ -598,7 +604,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
* @return The content section to which this item belongs * @return The content section to which this item belongs
*/ */
public ContentSection getContentSection() { public ContentSection getContentSection() {
return (ContentSection) DomainObjectFactory.newInstance((DataObject) get(CONTENT_SECTION)); return (ContentSection) DomainObjectFactory.newInstance((DataObject) get(
CONTENT_SECTION));
} }
/** /**
@ -694,7 +701,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
* @return the items on the path to the root folder. * @return the items on the path to the root folder.
*/ */
public ItemCollection getPathInfo(boolean includeSelf) { public ItemCollection getPathInfo(boolean includeSelf) {
DataCollection collection = SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE); DataCollection collection = SessionManager.getSession().retrieve(
BASE_DATA_OBJECT_TYPE);
String ids = (String) get(ANCESTORS); String ids = (String) get(ANCESTORS);
if (ids == null) { if (ids == null) {
@ -858,7 +866,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
DataQuery versions = getSession().retrieveQuery(QUERY_PENDING_ITEMS); DataQuery versions = getSession().retrieveQuery(QUERY_PENDING_ITEMS);
versions.setParameter("itemID", getDraftVersion().getID()); versions.setParameter("itemID", getDraftVersion().getID());
return new ItemCollection(new DataQueryDataCollectionAdapter(versions, "item")); return new ItemCollection(new DataQueryDataCollectionAdapter(versions,
"item"));
} }
/** /**
@ -934,13 +943,15 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
s_log.debug("m_live miss"); s_log.debug("m_live miss");
final DataAssociationCursor versions = final DataAssociationCursor versions =
((DataAssociation) get(VERSIONS)).cursor(); ((DataAssociation) get(VERSIONS)).cursor();
versions.addEqualsFilter(VERSION, LIVE); versions.addEqualsFilter(VERSION, LIVE);
try { try {
if (versions.next()) { if (versions.next()) {
ContentItem item = (ContentItem) DomainObjectFactory.newInstance(versions.getDataObject()); ContentItem item =
(ContentItem) DomainObjectFactory.newInstance(versions.
getDataObject());
return m_live.set(item); return m_live.set(item);
} }
return m_live.set(null); return m_live.set(null);
@ -1068,18 +1079,18 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
public void setLive(final ContentItem version) { public void setLive(final ContentItem version) {
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("Setting item " + this + " live with version " s_log.debug("Setting item " + this + " live with version "
+ version); + version);
} }
if (Assert.isEnabled()) { if (Assert.isEnabled()) {
Assert.isTrue(version == null || LIVE.equals(version.getVersion()), Assert.isTrue(version == null || LIVE.equals(version.getVersion()),
"Item version " + version + " must be null or " "Item version " + version + " must be null or "
+ "the live version"); + "the live version");
} }
if (isLive()) { if (isLive()) {
s_log.debug("The item is already live; getting the current " s_log.debug("The item is already live; getting the current "
+ "live version"); + "live version");
final ContentItem oldVersion = getLiveVersion(); final ContentItem oldVersion = getLiveVersion();
@ -1096,7 +1107,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
// XXX We don't need to use a custom query here // XXX We don't need to use a custom query here
// anymore. // anymore.
final DataQuery items = final DataQuery items =
SessionManager.getSession().retrieveQuery("com.arsdigita.cms.getLiveItemsWithSameParent"); SessionManager.getSession().retrieveQuery(
"com.arsdigita.cms.getLiveItemsWithSameParent");
items.addNotEqualsFilter("id", oldVersion.getID()); items.addNotEqualsFilter("id", oldVersion.getID());
items.setParameter("itemId", oldVersion.getID()); items.setParameter("itemId", oldVersion.getID());
@ -1109,7 +1121,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug(oldVersion + " is the last child of " s_log.debug(oldVersion + " is the last child of "
+ parent); + parent);
} }
} }
@ -1131,14 +1143,14 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
if (parent instanceof ContentBundle || parent instanceof Folder) { if (parent instanceof ContentBundle || parent instanceof Folder) {
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("Parent of " + oldVersion + " is " + parent s_log.debug("Parent of " + oldVersion + " is " + parent
+ "; unpublishing the parent"); + "; unpublishing the parent");
} }
((ContentItem) parent).setLive(null); ((ContentItem) parent).setLive(null);
} }
s_log.debug("Setting the live version association to null and " s_log.debug("Setting the live version association to null and "
+ "saving"); + "saving");
setLiveVersion(null); setLiveVersion(null);
@ -1147,7 +1159,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
if (version != null) { if (version != null) {
s_log.debug("The new version is not null; setting the live " s_log.debug("The new version is not null; setting the live "
+ "version association"); + "version association");
setLiveVersion(version); setLiveVersion(version);
@ -1174,15 +1186,15 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
* @return the new pending version * @return the new pending version
*/ */
public ContentItem publish(final LifecycleDefinition cycleDef, public ContentItem publish(final LifecycleDefinition cycleDef,
final Date startDate) { final Date startDate) {
applyTag("Published"); applyTag("Published");
Versions.suspendVersioning(); Versions.suspendVersioning();
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("Publishing item " + this + " with lifecycle " s_log.debug("Publishing item " + this + " with lifecycle "
+ "definition " + cycleDef + " and start date " + "definition " + cycleDef + " and start date "
+ startDate); + startDate);
} }
/* amended Chris Gilbert /* amended Chris Gilbert
* *
@ -1196,7 +1208,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
if (listener == null) { if (listener == null) {
listener = getPublishListenerClassName(); listener = getPublishListenerClassName();
} }
final Lifecycle cycle = cycleDef.createFullLifecycle(startDate, listener); final Lifecycle cycle =
cycleDef.createFullLifecycle(startDate, listener);
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("Instantiated lifecycle " + cycle); s_log.debug("Instantiated lifecycle " + cycle);
@ -1212,15 +1225,16 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
if (Assert.isEnabled()) { if (Assert.isEnabled()) {
Assert.exists(pending, ContentItem.class); Assert.exists(pending, ContentItem.class);
Assert.isTrue(PENDING.equals(pending.getVersion()) Assert.isTrue(PENDING.equals(pending.getVersion())
|| LIVE.equals(pending.getVersion()), || LIVE.equals(pending.getVersion()),
"The new pending item must be pending or live; " "The new pending item must be pending or live; "
+ "instead it is " + pending.getVersion()); + "instead it is " + pending.getVersion());
} }
return pending; return pending;
} }
public String getPublishListenerClassName() { public String getPublishListenerClassName() {
String className = ContentSection.getConfig().getPublishLifecycleListenerClass(); String className = ContentSection.getConfig().
getPublishLifecycleListenerClass();
if (className != null && !"".equals(className)) { if (className != null && !"".equals(className)) {
return className; return className;
} else { } else {
@ -1243,8 +1257,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
if (isLive()) { if (isLive()) {
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("The item is currently live; removing the " s_log.debug("The item is currently live; removing the "
+ "lifecycle of the public version, " + "lifecycle of the public version, "
+ getPublicVersion()); + getPublicVersion());
} }
removeLifecycle(getPublicVersion()); removeLifecycle(getPublicVersion());
@ -1319,7 +1333,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
if (lifecycle == null) { if (lifecycle == null) {
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("The item has no lifecycle; checking if the " s_log.debug("The item has no lifecycle; checking if the "
+ "public version has a lifecycle"); + "public version has a lifecycle");
} }
final ContentItem pub = getPublicVersion(); final ContentItem pub = getPublicVersion();
@ -1333,7 +1347,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("The public version has a lifecycle; " s_log.debug("The public version has a lifecycle; "
+ "returning " + cyclelife); + "returning " + cyclelife);
} }
return cyclelife; return cyclelife;
@ -1382,7 +1396,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("Removing lifecycle instance from item " s_log.debug("Removing lifecycle instance from item "
+ itemToRemove); + itemToRemove);
} }
LifecycleService.removeLifecycle(itemToRemove); LifecycleService.removeLifecycle(itemToRemove);
@ -1434,11 +1448,12 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
} }
Category root = Category.getRootForObject(getContentSection(), useContext); Category root = Category.getRootForObject(getContentSection(),
useContext);
if (null == root) { if (null == root) {
s_log.warn("No root category for " s_log.warn("No root category for "
+ getContentSection().getOID().toString() + getContentSection().getOID().toString()
+ " with context " + useContext); + " with context " + useContext);
return Collections.EMPTY_LIST.iterator(); return Collections.EMPTY_LIST.iterator();
} }
@ -1533,6 +1548,10 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
public ContentItem copy() { public ContentItem copy() {
return copy(null, false); return copy(null, false);
} }
public ContentItem copy(String lang) {
return copy(null, false, lang);
}
/** /**
* Recursively copy this item, creating a clone. * Recursively copy this item, creating a clone.
@ -1548,7 +1567,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
* @return the new copy of the item * @return the new copy of the item
* @see #copyServicesFrom(ContentItem) * @see #copyServicesFrom(ContentItem)
*/ */
final public ContentItem copy(final ContentItem newParent, final boolean copyServices) { final public ContentItem copy(final ContentItem newParent,
final boolean copyServices) {
ContentItem newItem = makeCopy(); ContentItem newItem = makeCopy();
if (newParent != null) { if (newParent != null) {
newItem.setParent(newParent); newItem.setParent(newParent);
@ -1558,6 +1578,21 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
} }
return newItem; return newItem;
} }
final public ContentItem copy(final ContentItem newParent,
final boolean copyServices,
final String lang) {
ContentItem newItem = makeCopy(lang);
if (newParent != null) {
newItem.setParent(newParent);
}
if (copyServices) {
newItem.copyServicesFrom(this);
}
return newItem;
}
/** /**
* Performs the actual mechanics of copying a content item. * Performs the actual mechanics of copying a content item.
@ -1579,6 +1614,29 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
return newItem; return newItem;
} }
/**
* Variant of {@link ACSObject#makeCopy} which allows to pass the (further)
* language of the copy.
*
* @param language
* @return
*/
protected ContentItem makeCopy(String language) {
if (s_log.isDebugEnabled()) {
s_log.debug("Copy taking place", new Throwable("trace"));
}
LanguageAwareObjectCopier copier = new LanguageAwareObjectCopier(
language);
final ContentItem newItem = copier.copyItem(this);
// Doesn't seem like I should have to do this, but what the hell
newItem.setContentSection(getContentSection());
newItem.save();
return newItem;
}
/** /**
* Transfer services, such as categories, * Transfer services, such as categories,
* from the passed-in item to this item. This method should be * from the passed-in item to this item. This method should be
@ -1653,7 +1711,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
setLive(pending); setLive(pending);
ContentBundle draftBundle = getBundle(); ContentBundle draftBundle = getBundle();
ContentBundle liveBundle = pending.getBundle(); ContentBundle liveBundle = pending.getBundle();
if (draftBundle != null && liveBundle != null && !liveBundle.isLiveVersion()) { if (draftBundle != null && liveBundle != null && !liveBundle.
isLiveVersion()) {
draftBundle.promotePendingVersion(liveBundle); draftBundle.promotePendingVersion(liveBundle);
} }
@ -1669,7 +1728,7 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
*/ */
protected void setVersionRecursively(final String version) { protected void setVersionRecursively(final String version) {
s_log.debug("Recursively updating the version attribute of the " s_log.debug("Recursively updating the version attribute of the "
+ "item"); + "item");
new VersionUpdater(version).updateItemVersion(this); new VersionUpdater(version).updateItemVersion(this);
} }
@ -1702,9 +1761,10 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
* @deprecated use {@link #copyProperty(CustomCopy, Property, ItemCopier)} instead * @deprecated use {@link #copyProperty(CustomCopy, Property, ItemCopier)} instead
*/ */
protected final boolean copyProperty(final ContentItem source, protected final boolean copyProperty(final ContentItem source,
final String attribute, final String attribute,
final ItemCopier copier) { final ItemCopier copier) {
throw new UnsupportedOperationException("use copyProperty(CustomCopy, Property, ItemCopier) for copying"); throw new UnsupportedOperationException(
"use copyProperty(CustomCopy, Property, ItemCopier) for copying");
} }
/** /**
@ -1793,8 +1853,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
* to copy the property. * to copy the property.
*/ */
public boolean copyProperty(final CustomCopy source, public boolean copyProperty(final CustomCopy source,
final Property property, final Property property,
final ItemCopier copier) { final ItemCopier copier) {
String attribute = property.getName(); String attribute = property.getName();
if (CHILDREN.equals(attribute)) { if (CHILDREN.equals(attribute)) {
return true; return true;
@ -1822,26 +1882,29 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
// If live Bundle already exists, recategorize. // If live Bundle already exists, recategorize.
if (PARENT.equals(attribute)) { if (PARENT.equals(attribute)) {
ACSObject parent = ((ContentItem) source).getParent(); ACSObject parent = ((ContentItem) source).getParent();
if (parent != null && copier.getCopyType() == ItemCopier.VERSION_COPY) { if (parent != null && copier.getCopyType()
== ItemCopier.VERSION_COPY) {
if (parent instanceof ContentBundle) { if (parent instanceof ContentBundle) {
ContentBundle bundle = (ContentBundle) parent; ContentBundle bundle = (ContentBundle) parent;
ContentBundle liveBundle = (ContentBundle) bundle.getPublicVersion(); ContentBundle liveBundle = (ContentBundle) bundle.
getPublicVersion();
if (liveBundle == null) { if (liveBundle == null) {
liveBundle = (ContentBundle) bundle.createPendingVersion(null); liveBundle =
(ContentBundle) bundle.createPendingVersion(null);
} else { } else {
Set liveCatSet = new HashSet(); Set liveCatSet = new HashSet();
Set draftCatSet = new HashSet(); Set draftCatSet = new HashSet();
CategoryCollection liveCategories = CategoryCollection liveCategories =
liveBundle.getCategoryCollection(); liveBundle.getCategoryCollection();
while (liveCategories.next()) { while (liveCategories.next()) {
liveCatSet.add(liveCategories.getCategory()); liveCatSet.add(liveCategories.getCategory());
} }
liveCategories.close(); liveCategories.close();
CategoryCollection draftCategories = CategoryCollection draftCategories =
bundle.getCategoryCollection(); bundle.getCategoryCollection();
while (draftCategories.next()) { while (draftCategories.next()) {
draftCatSet.add(draftCategories.getCategory()); draftCatSet.add(draftCategories.getCategory());
} }
@ -1854,7 +1917,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
Iterator removeIter = catsToRemove.iterator(); Iterator removeIter = catsToRemove.iterator();
while (removeIter.hasNext()) { while (removeIter.hasNext()) {
liveBundle.removeCategory((Category) removeIter.next()); liveBundle.removeCategory(
(Category) removeIter.next());
} }
Iterator addIter = catsToAdd.iterator(); Iterator addIter = catsToAdd.iterator();
while (addIter.hasNext()) { while (addIter.hasNext()) {
@ -1932,7 +1996,8 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
// slp.getLocale() // slp.getLocale()
try { try {
locale = Locale.fromJavaLocale(new java.util.Locale(getLanguage(), "")); locale = Locale.fromJavaLocale(new java.util.Locale(getLanguage(),
""));
} catch (GlobalizationException e) { } catch (GlobalizationException e) {
s_log.warn("GlobalizationException thrown in getLocale()", e); s_log.warn("GlobalizationException thrown in getLocale()", e);
throw new UncheckedWrapperException(e.getMessage()); throw new UncheckedWrapperException(e.getMessage());
@ -2024,20 +2089,26 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
super.beforeDelete(); super.beforeDelete();
// remove Link associations to this // remove Link associations to this
DataCollection dc = SessionManager.getSession().retrieve(Link.BASE_DATA_OBJECT_TYPE); DataCollection dc = SessionManager.getSession().retrieve(
Link.BASE_DATA_OBJECT_TYPE);
dc.addEqualsFilter(Link.TARGET_ITEM + "." + ACSObject.ID, dc.addEqualsFilter(Link.TARGET_ITEM + "." + ACSObject.ID,
getID()); getID());
while (dc.next()) { while (dc.next()) {
Link link = (Link) DomainObjectFactory.newInstance(dc.getDataObject()); Link link = (Link) DomainObjectFactory.newInstance(
dc.getDataObject());
link.setTargetItem(null); link.setTargetItem(null);
} }
// remove ContentGroup associations to this // remove ContentGroup associations to this
dc = SessionManager.getSession().retrieve(ContentGroupAssociation.BASE_DATA_OBJECT_TYPE); dc = SessionManager.getSession().retrieve(
dc.addEqualsFilter(ContentGroupAssociation.CONTENT_ITEM + "." + ACSObject.ID, ContentGroupAssociation.BASE_DATA_OBJECT_TYPE);
getID()); dc.addEqualsFilter(ContentGroupAssociation.CONTENT_ITEM + "."
+ ACSObject.ID,
getID());
while (dc.next()) { while (dc.next()) {
ContentGroupAssociation groupAssoc = (ContentGroupAssociation) DomainObjectFactory.newInstance(dc.getDataObject()); ContentGroupAssociation groupAssoc =
(ContentGroupAssociation) DomainObjectFactory.
newInstance(dc.getDataObject());
groupAssoc.setContentItem(null); groupAssoc.setContentItem(null);
} }
} }
@ -2110,5 +2181,4 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
public List getExtraXMLGenerators() { public List getExtraXMLGenerators() {
return extraXMLGenerators; return extraXMLGenerators;
} }
} }

View File

@ -47,10 +47,9 @@ import java.util.Iterator;
class DomainCopier extends DomainService { class DomainCopier extends DomainService {
private static Logger s_log = Logger.getLogger(DomainCopier.class); private static Logger s_log = Logger.getLogger(DomainCopier.class);
// A map of OID => DomainObject // A map of OID => DomainObject
private final HashMap m_copied; private final HashMap m_copied;
private final TraversedSet m_traversed; protected final TraversedSet m_traversed;
final Tracer m_trace; final Tracer m_trace;
/** /**
@ -69,7 +68,7 @@ class DomainCopier extends DomainService {
* *
* @param source the <code>DomainObject</code> from which to copy * @param source the <code>DomainObject</code> from which to copy
*/ */
public DomainObject copy(final DomainObject source) { public DomainObject copy(final DomainObject source) {
m_trace.enter("copy", source); m_trace.enter("copy", source);
final OID sourceOID = source.getOID(); final OID sourceOID = source.getOID();
@ -90,15 +89,15 @@ class DomainCopier extends DomainService {
if (source instanceof ACSObject) { if (source instanceof ACSObject) {
final String type = final String type =
((ACSObject) source).getSpecificObjectType(); ((ACSObject) source).getSpecificObjectType();
target = (DomainObject)Classes.newInstance( target = (DomainObject) Classes.newInstance(
clacc, clacc,
new Class[] { String.class }, new Class[]{String.class},
new Object[] { type }); new Object[]{type});
} else { } else {
Assert.fail("Cannot copy " + source + "; it is not an " + Assert.fail("Cannot copy " + source + "; it is not an "
"ACSObject"); + "ACSObject");
// XXX Contrary to this assertion, it is reasonable to // XXX Contrary to this assertion, it is reasonable to
// copy domain objects, and this code should support // copy domain objects, and this code should support
// it. // it.
@ -129,59 +128,59 @@ class DomainCopier extends DomainService {
} }
protected void copyData(final DomainObject source, DomainObject target) { protected void copyData(final DomainObject source, DomainObject target) {
final ObjectType type = source.getObjectType(); final ObjectType type = source.getObjectType();
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("Using object type " + type.getName()); s_log.debug("Using object type " + type.getName());
}
// XXX This is what I would like to do:
//
//final Iterator iter = type.getProperties();
//
//while (iter.hasNext()) {
// copyProperty(source, target, (Property) iter.next());
//}
// But the beforeSave-on-flush behavior makes it so I have
// to do this instead:
Iterator iter = type.getProperties();
final ArrayList attributes = new ArrayList();
final ArrayList roles = new ArrayList();
final ArrayList collections = new ArrayList();
while (iter.hasNext()) {
final Property prop = (Property) iter.next();
if (prop.isAttribute()) {
attributes.add(prop);
} else if (prop.isCollection()) {
collections.add(prop);
} else {
roles.add(prop);
} }
}
// XXX This is what I would like to do: iter = attributes.iterator();
//
//final Iterator iter = type.getProperties();
//
//while (iter.hasNext()) {
// copyProperty(source, target, (Property) iter.next());
//}
// But the beforeSave-on-flush behavior makes it so I have while (iter.hasNext()) {
// to do this instead: copyProperty(source, target, (Property) iter.next());
}
Iterator iter = type.getProperties(); iter = roles.iterator();
final ArrayList attributes = new ArrayList();
final ArrayList roles = new ArrayList();
final ArrayList collections = new ArrayList();
while (iter.hasNext()) { while (iter.hasNext()) {
final Property prop = (Property) iter.next(); copyProperty(source, target, (Property) iter.next());
}
if (prop.isAttribute()) { iter = collections.iterator();
attributes.add(prop);
} else if (prop.isCollection()) {
collections.add(prop);
} else {
roles.add(prop);
}
}
iter = attributes.iterator(); while (iter.hasNext()) {
copyProperty(source, target, (Property) iter.next());
}
while (iter.hasNext()) {
copyProperty(source, target, (Property) iter.next());
}
iter = roles.iterator();
while (iter.hasNext()) {
copyProperty(source, target, (Property) iter.next());
}
iter = collections.iterator();
while (iter.hasNext()) {
copyProperty(source, target, (Property) iter.next());
}
} }
/** /**
@ -211,8 +210,8 @@ class DomainCopier extends DomainService {
} }
if (prop.isKeyProperty()) { if (prop.isKeyProperty()) {
s_log.debug("The property is one of the key properties; " + s_log.debug("The property is one of the key properties; "
"skipping it"); + "skipping it");
} else { } else {
s_log.debug("Copying is enabled; proceeding"); s_log.debug("Copying is enabled; proceeding");
@ -281,8 +280,8 @@ class DomainCopier extends DomainService {
final String name = prop.getName(); final String name = prop.getName();
if (m_traversed.contains(source, prop)) { if (m_traversed.contains(source, prop)) {
s_log.debug("The role belongs to a link that has " + s_log.debug("The role belongs to a link that has "
"already been traversed; skipping it"); + "already been traversed; skipping it");
} else { } else {
// This marks the forward link traversed. Further down, // This marks the forward link traversed. Further down,
// in this method and in copyCollection, we mark the // in this method and in copyCollection, we mark the
@ -363,12 +362,13 @@ class DomainCopier extends DomainService {
m_traversed.add(selem, reverse); m_traversed.add(selem, reverse);
final DomainObject telem = copy(source, target, selem, prop); final DomainObject telem = copy(source, target, selem, prop);
DataObject tgtLink = null; DataObject tgtLink = null;
// removing this assert since copy will return null in the // removing this assert since copy will return null in the
// case of deferred association creation in VersionCopier // case of deferred association creation in VersionCopier
//Assert.exists(telem, DomainObject.class); //Assert.exists(telem, DomainObject.class);
if (telem != null) { if (telem != null) {
tgtLink = add(target, name, telem); tgtLink = add(target, name, telem);
} }
@ -410,8 +410,7 @@ class DomainCopier extends DomainService {
if (prop.isComponent()) { if (prop.isComponent()) {
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
s_log.debug("The property is a component; " + s_log.debug("The property is a component; " + "copying by value");
"copying by value");
} }
final DomainObject copy = copy(object); final DomainObject copy = copy(object);
@ -420,8 +419,8 @@ class DomainCopier extends DomainService {
return copy; return copy;
} else { } else {
s_log.debug("The property is not a component; " + s_log.debug("The property is not a component; "
"copying by reference"); + "copying by reference");
m_trace.exit("copy", object); m_trace.exit("copy", object);
@ -442,10 +441,8 @@ class DomainCopier extends DomainService {
return (DomainObject) m_copied.get(oid); return (DomainObject) m_copied.get(oid);
} }
// Utility methods and classes // Utility methods and classes
protected DomainObject domain(final DataObject data) {
private DomainObject domain(final DataObject data) {
Assert.exists(data, DataObject.class); Assert.exists(data, DataObject.class);
final DomainObject domain = DomainObjectFactory.newInstance(data); final DomainObject domain = DomainObjectFactory.newInstance(data);
@ -455,7 +452,8 @@ class DomainCopier extends DomainService {
return domain; return domain;
} }
private static class TraversedSet extends HashSet { protected static class TraversedSet extends HashSet {
void add(final DomainObject object, final Property prop) { void add(final DomainObject object, final Property prop) {
Assert.exists(object, DomainObject.class); Assert.exists(object, DomainObject.class);
@ -472,14 +470,15 @@ class DomainCopier extends DomainService {
return contains(object.getOID() + "." + prop.getName()); return contains(object.getOID() + "." + prop.getName());
} }
} }
private final class WrapperDomainObject extends DomainObject{
protected final class WrapperDomainObject extends DomainObject {
public WrapperDomainObject(DataObject dobj) { public WrapperDomainObject(DataObject dobj) {
super(dobj); super(dobj);
} }
public WrapperDomainObject(OID oid) { public WrapperDomainObject(OID oid) {
super(oid); super(oid);
} }
} }
} }

View File

@ -0,0 +1,76 @@
package com.arsdigita.cms;
import com.arsdigita.domain.DomainObject;
import com.arsdigita.persistence.DataAssociation;
import com.arsdigita.persistence.DataAssociationCursor;
import com.arsdigita.persistence.DataObject;
import com.arsdigita.persistence.metadata.Property;
import org.apache.log4j.Logger;
/**
*
* @author Jens Pelzetter
* @version $Id$
*/
public class LanguageAwareObjectCopier extends ObjectCopier {
private static final Logger logger =
Logger.getLogger(LanguageAwareObjectCopier.class);
private String language;
public LanguageAwareObjectCopier(String language) {
super();
this.language = language;
}
@Override
protected void copyCollection(final DomainObject source,
final DomainObject target,
final Property prop) {
if (source instanceof ContentPage) {
if (logger.isDebugEnabled()) {
logger.debug("Copying collection " + prop);
}
final String name = prop.getName();
final DataAssociation sass = (DataAssociation) get(source, name);
final DataAssociationCursor scursor = sass.cursor();
final Property reverse = prop.getAssociatedProperty();
while (scursor.next()) {
final DomainObject selem = domain(scursor.getDataObject());
m_traversed.add(selem, reverse);
DomainObject telem = copy(source, target, selem, prop);
if (telem instanceof ContentPage) {
ContentPage tpage = (ContentPage) telem;
telem = tpage.getContentBundle().getInstance(language);
}
DataObject tgtLink = null;
// removing this assert since copy will return null in the
// case of deferred association creation in VersionCopier
//Assert.exists(telem, DomainObject.class);
if (telem != null) {
tgtLink = add(target, name, telem);
}
if (tgtLink != null) {
// Copy link attributes as well
copyData(new WrapperDomainObject(scursor.getLink()),
new WrapperDomainObject(tgtLink));
}
}
} else {
//Use old behaviour
super.copyCollection(source, target, prop);
}
}
}

View File

@ -156,7 +156,7 @@ public class ItemLanguages extends LayoutPanel {
ContentType type = item.getContentType(); ContentType type = item.getContentType();
item = (ContentPage) item.copy(); item = (ContentPage) item.copy(lang);
item.setLanguage(lang); item.setLanguage(lang);
item.setName(name); item.setName(name);

View File

@ -77,9 +77,31 @@ public class SciDepartmentOrganizationForm
getSelectedObject(state); getSelectedObject(state);
if (this.getSaveCancelSection().getSaveButton().isSelected(state)) { if (this.getSaveCancelSection().getSaveButton().isSelected(state)) {
department.setOrganization((SciOrganization) data.get(ITEM_SEARCH)); SciOrganization orga = (SciOrganization) data.get(ITEM_SEARCH);
orga = (SciOrganization) orga.getContentBundle().getInstance(department.getLanguage());
department.setOrganization(orga);
//department.setOrganization((SciOrganization) data.get(ITEM_SEARCH));
}
init(fse);
}
init(fse); @Override
public void validate(FormSectionEvent fse) throws FormProcessException {
final PageState state = fse.getPageState();
final FormData data = fse.getFormData();
SciDepartment department = (SciDepartment) getItemSelectionModel().
getSelectedObject(state);
SciOrganization orga = (SciOrganization) data.get(ITEM_SEARCH);
if (!(orga.getContentBundle().hasInstance(department.getLanguage()))) {
data.addError(
SciOrganizationGlobalizationUtil.globalize(
"sciorganization.ui.department.organization.add.no_suitable_language_variant"));
} }
} }
} }

View File

@ -22,6 +22,7 @@ package com.arsdigita.cms.contenttypes.ui;
import com.arsdigita.bebop.Component; import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.ControlLink; import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.Label; import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Link;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Table; import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.event.TableActionEvent; import com.arsdigita.bebop.event.TableActionEvent;
@ -31,12 +32,19 @@ import com.arsdigita.bebop.table.TableColumn;
import com.arsdigita.bebop.table.TableColumnModel; import com.arsdigita.bebop.table.TableColumnModel;
import com.arsdigita.bebop.table.TableModel; import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.bebop.table.TableModelBuilder; 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.ItemSelectionModel;
import com.arsdigita.cms.SecurityManager; import com.arsdigita.cms.SecurityManager;
import com.arsdigita.cms.contenttypes.SciDepartment; import com.arsdigita.cms.contenttypes.SciDepartment;
import com.arsdigita.cms.contenttypes.SciOrganization; import com.arsdigita.cms.contenttypes.SciOrganization;
import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.cms.dispatcher.Utilities; import com.arsdigita.cms.dispatcher.Utilities;
import com.arsdigita.dispatcher.ObjectNotFoundException;
import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.util.LockableImpl; import com.arsdigita.util.LockableImpl;
import java.math.BigDecimal;
import org.apache.log4j.Logger;
/** /**
* Sheet for showing the superior organization of a SciDepartment. * Sheet for showing the superior organization of a SciDepartment.
@ -49,6 +57,9 @@ public class SciDepartmentOrganizationSheet
extends Table extends Table
implements TableActionListener { implements TableActionListener {
private static final Logger logger =
Logger.getLogger(
SciDepartmentOrganizationSheet.class);
private final String TABLE_COL_EDIT = "table_col_edit"; private final String TABLE_COL_EDIT = "table_col_edit";
private final String TABLE_COL_DEL = "table_col_del"; private final String TABLE_COL_DEL = "table_col_del";
private ItemSelectionModel m_itemModel; private ItemSelectionModel m_itemModel;
@ -169,8 +180,57 @@ public class SciDepartmentOrganizationSheet
Object key, Object key,
int row, int row,
int column) { int column) {
Label label = new Label(value.toString()); SecurityManager securityManager =
return label; Utilities.getSecurityManager(state);
SciDepartment department = (SciDepartment) m_itemModel.
getSelectedObject(state);
boolean canEdit = securityManager.canAccess(
state.getRequest(),
SecurityManager.EDIT_ITEM,
department);
if (canEdit) {
SciOrganization organization;
try {
organization = new SciOrganization((BigDecimal) key);
} catch (ObjectNotFoundException ex) {
logger.warn(String.format("No object with key '%s' found.",
key),
ex);
return new Label(value.toString());
}
ContentSection section = CMS.getContext().getContentSection();
ItemResolver resolver = section.getItemResolver();
Link link = new Link(String.format("%s (%s)",
value.toString(),
organization.getLanguage()),
resolver.generateItemURL(state,
organization,
section,
organization.
getVersion()));
return link;
} else {
SciOrganization organization;
try {
organization = new SciOrganization((BigDecimal) key);
} catch (ObjectNotFoundException ex) {
logger.warn(String.format("No object with key '%s' found.",
key),
ex);
return new Label(value.toString());
}
Label label = new Label(
String.format("%s (%s)",
value.toString(),
organization.getLanguage()));
return label;
}
} }
} }
@ -216,7 +276,8 @@ public class SciDepartmentOrganizationSheet
public void cellSelected(TableActionEvent event) { public void cellSelected(TableActionEvent event) {
PageState state = event.getPageState(); PageState state = event.getPageState();
SciDepartment department = (SciDepartment) m_itemModel.getSelectedObject( SciDepartment department =
(SciDepartment) m_itemModel.getSelectedObject(
state); state);
TableColumn column = getColumnModel().get(event.getColumn().intValue()); TableColumn column = getColumnModel().get(event.getColumn().intValue());

View File

@ -78,10 +78,33 @@ public class SciOrganizationDepartmentAddForm
getSelectedObject(state); getSelectedObject(state);
if (!(this.getSaveCancelSection().getCancelButton(). if (!(this.getSaveCancelSection().getCancelButton().
isSelected(state))) { isSelected(state))) {
orga.addDepartment((SciDepartment) data.get(ITEM_SEARCH)); SciDepartment department = (SciDepartment) data.get(ITEM_SEARCH);
department = (SciDepartment) department.getContentBundle().
getInstance(orga.getLanguage());
orga.addDepartment(department);
//orga.addDepartment((SciDepartment) data.get(ITEM_SEARCH));
} }
init(fse); init(fse);
} }
@Override
public void validate(FormSectionEvent fse) throws FormProcessException {
final PageState state = fse.getPageState();
final FormData data = fse.getFormData();
SciOrganization orga = (SciOrganization) getItemSelectionModel().
getSelectedObject(state);
SciDepartment department = (SciDepartment) data.get(ITEM_SEARCH);
if (!(department.getContentBundle().hasInstance(orga.getLanguage()))) {
data.addError(
SciOrganizationGlobalizationUtil.globalize(
"sciorganization.ui.organization.department.add.no_suitable_language_variant"));
}
}
} }

View File

@ -221,12 +221,13 @@ public class SciOrganizationDepartmentsTable
key), key),
ex); ex);
return new Label(value.toString()); return new Label(value.toString());
} }
ContentSection section = CMS.getContext().getContentSection(); ContentSection section = CMS.getContext().getContentSection();
ItemResolver resolver = section.getItemResolver(); ItemResolver resolver = section.getItemResolver();
Link link = new Link(value.toString(), Link link = new Link(String.format("%s (%s)",
value.toString(),
department.getLanguage()),
resolver.generateItemURL(state, resolver.generateItemURL(state,
department, department,
section, section,
@ -236,7 +237,19 @@ public class SciOrganizationDepartmentsTable
return link; return link;
} else { } else {
Label label = new Label(value.toString()); SciDepartment department;
try {
department = new SciDepartment((BigDecimal) key);
} catch (ObjectNotFoundException ex) {
s_log.warn(String.format("No object with key '%s' found.",
key),
ex);
return new Label(value.toString());
}
Label label = new Label(String.format("%s (%s)",
value.toString(),
department.getLanguage()));
return label; return label;
} }
} }

View File

@ -178,3 +178,5 @@ scimember.ui.project.confirm_remove=Do you really want to remove this associatio
scimember.ui.project.select_project=Project scimember.ui.project.select_project=Project
scimember.ui.projects.edit_assoc=Edit association scimember.ui.projects.edit_assoc=Edit association
sciorganization.ui.project.description=Description of project sciorganization.ui.project.description=Description of project
sciorganization.ui.organization.department.add.no_suitable_language_variant=The selected item has no language variant for the language of the current item. Please add an suitable language variant to the item to add before adding it.
sciorganization.ui.department.organization.add.no_suitable_language_variant=The selected item has no language variant for the language of the current item. Please add an suitable language variant to the item to add before adding it.

View File

@ -178,3 +178,5 @@ scimember.ui.project.confirm_remove=Wollen Sie diese Verkn\u00fcpfung wirklich e
scimember.ui.project.select_project=Projekt scimember.ui.project.select_project=Projekt
scimember.ui.projects.edit_assoc=Verkn\u00fcpfung bearbeiten scimember.ui.projects.edit_assoc=Verkn\u00fcpfung bearbeiten
sciorganization.ui.project.description=Projektbeschreibung sciorganization.ui.project.description=Projektbeschreibung
sciorganization.ui.organization.department.add.no_suitable_language_variant=Das ausgew\u00e4hlte ContentItem besitzt keine Sprachvariante f\u00fcr die Sprache dieses Items und kann daher nicht hinzugef\u00fcgt werden.
sciorganization.ui.department.organization.add.no_suitable_language_variant=Das ausgew\u00e4hlte ContentItem besitzt keine Sprachvariante f\u00fcr die Sprache dieses Items und kann daher nicht hinzugef\u00fcgt werden.