/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms;
import com.arsdigita.domain.DomainObject;
import com.arsdigita.persistence.metadata.Property;
import org.apache.log4j.Logger;
/**
* Recursively copies a DataObject, and all of its composite sub-objects.
* This class implements ItemCopier by maintaining a Map of
* OID->DataObject of all objects copied so far. This ensures that no
* infinite recursion loops ever occur.
*
* The {@link #copyItem(ContentItem)} method attempts to copy an item by * using the following steps: *
* ObjectCopier has package-scope since it will only be accessed from
* {@link ContentItem}, as part of the internal implementation of the
* {@link ContentItem#copy()} method. Classes outside the package should not
* attempt to call methods on this class directly, since the results may
* prove dangerous.
*
*
* @author Stanislav Freidin
* @version $Id: ObjectCopier.java 754 2005-09-02 13:26:17Z sskracic $
* @see ContentItem
* @see ContentItem#copyProperty(ContentItem, String, ItemCopier)
*/
class ObjectCopier extends DomainCopier implements ItemCopier {
public static final String versionId =
"$Id: ObjectCopier.java 754 2005-09-02 13:26:17Z sskracic $" +
"$Author: sskracic $" +
"$DateTime: 2004/08/17 23:15:09 $";
private static Logger s_log = Logger.getLogger(ObjectCopier.class);
/**
* This copier is used to create plain copies for items
*/
public int getCopyType() {
return ItemCopier.PLAIN_COPY;
}
/**
* Copy a {@link ContentItem}, along with all of its component
* sub-objects, and return the copy. Note that the categories to
* which the source item belongs are not automatically transferred
* to the copy; the user must call {@link #copyServices(ContentItem,
* ContentItem)} in order to transfer the categories and other
* services.
*
* @param item the item to be copied
* @return a copy of the item
*/
public ContentItem copyItem(ContentItem item) {
final ContentItem copy = (ContentItem) copy(item);
return copy;
}
/**
* Copies properties. This method is called from {@link
* #copy(DomainObject)} for each property of the object being
* copied.
*
* This implementation calls {@link CustomCopy#copyProperty(CustomCopy,
* Property, itemCopier)} if source and
* target implement CustomCopy, and only
* call super.copyProperty if the above returns false.
*
*
* @param source the DomainObject being copied
* @param target the new copy
* @param prop the Property currently under
* consideration
*/
protected void copyProperty(final DomainObject source,
final DomainObject target,
final Property prop) {
m_trace.enter("copyProperty", source, target, prop);
if (target instanceof CustomCopy) {
final CustomCopy sitem = (CustomCopy) source;
final CustomCopy titem = (CustomCopy) target;
if (titem.copyProperty(sitem, prop, this)) {
s_log.debug("The target item overrides the default " +
"behavior to propogate the property; " +
"skipping it");
m_trace.exit("copyProperty");
return;
}
}
super.copyProperty(source, target, prop);
m_trace.exit("copyProperty");
}
/**
* Creates a copy, by reference or by value, of the property
* represented in object.
*
* This implementation returns the result of {@link
* #copy(DomainObject)} if the property is a component and simply
* returns object if it is not.
*
* @param source the CustomCopy source (original)
* object to which this property belongs
* @param target the new CustomCopy copy to which
* the return value of this method will be attached
* @param object the DomainObject property being
* copied
* @param prop a Property representing
* object
* @return object if prop is not a
* component or a copy of object it is a component
* @throws UnsupportedOperationException if either source or
* target are not DomainObjects
*/
public DomainObject copy(final CustomCopy source,
final CustomCopy target,
final DomainObject object,
final Property prop) {
if ((source instanceof DomainObject) &&
(target instanceof DomainObject)) {
return copy((DomainObject) source, (DomainObject) target,
object, prop);
} else {
throw new UnsupportedOperationException
("CustomCopy implementations should be DomainObjects");
}
}
/**
* Transfer services from one {@link ContentItem} to another. For
* example, this method will be called to transfer the categories
* from the draft version of the item to the live version of the
* item.
*
* Note that the target item must have a valid item ID before this
* method is called. If the target item is new, it should be saved
* prior to calling copyServices.
*
* @param target the target item
* @param source the source item
*/
public static void copyServices(ContentItem target, ContentItem source) {
if (target.copyServices(source)) {
s_log.debug("The target item has opted to do its own " +
"service propogation");
} else {
// What goes here?
}
}
}