/*
 * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
 *
 * The contents of this file are subject to the CCM Public
 * License (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the
 * License at http://www.redhat.com/licenses/ccmpl.html.
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language
 * governing rights and limitations under the License.
 *
 */
package com.arsdigita.domain;

import com.arsdigita.persistence.DataObject;

/**
 * This abstract class provides an interface for DomainObjectFactory to
 * use in order to delegate the job of instantiating a domain object
 * from a data object to custom code.
 *
 * <p>
 * Whenever a developer adds a new data object type, if they want
 * the DomainObjectFactory to support the new data object type, then
 * they must register a DomainObjectInstantiator for the new type
 * using DomainObjectFactory.registerInstantiator().
 *
 * <p>
 * An instantiator is responsible for producing a DomainObject given
 * DataObject foo if the instantiator was registered for
 * foo's object type.
 *
 * <p>
 * The task of producing a DomainObject generally involves 2 parts:
 * <ol>
 * <li>optionally delegating to another instantiator based on properties
 * of the given DataObject, and
 * <li>instantiating a DomainObject if no further delegation should occur.
 * </ol>
 *
 * Typically, the logic for delegating to another instantiator is the
 * same for all data object types with a common base type (e.g. ACSObject).
 * For this reason, the task of producing a DomainObject is broken into
 * two methods that can be overrided independently.  The method
 * <code>resolveInstantiator()</code> examines the given DataObject and
 * returns a delegate instantiator.  The method doNewInstance() performs
 * the last step of producing a data object, generally assuming that
 * no futher delegation is necessary.  Typically the instantiator for
 * a base object type (e.g. ACSObjectInstantiator) will provide an
 * implementation of <code>resolveInstantiator()</code> that will work
 * for extended types as well, so an extended type's instantiator need
 * only override doInstantiate() (usually with only one line of code
 * to instantiate a DomainObject class for the data object type in
 * question).
 *
 * @see com.arsdigita.kernel.ACSObjectInstantiator
 * @see DomainObjectFactory
 * @see DomainObject
 * @see com.arsdigita.persistence.DataObject
 *
 * @author Oumi Mehrotra
 * @version 1.0
 **/
public abstract class DomainObjectInstantiator {

    public static final String versionId = "$Id: //core-platform/dev/src/com/arsdigita/domain/DomainObjectInstantiator.java#7 $ by $Author: dennis $, $DateTime: 2004/04/07 16:07:11 $";

    /**
     * Return a delegated instantiator.  Called from
     * DomainObjectFactory.newInstance().  If the returned instantiator
     * is <code>this</code>, then the factory will call
     * <code>this.doNewInstance()</code>.  Otherwise, the factory will
     * again call resolveInstantiator() on the returned instantiator,
     * repeating the process until finally an instantiator's
     * resolveInstantiator() method returns itself.
     *
     * @param dataObject The data object for which to find a
     * DomainObjectInstantiator.
     *
     * @return A domain object for this data object.
     */
    public DomainObjectInstantiator resolveInstantiator(DataObject dataObject) {
        return this;
    }

    /**
     * Construct a DomainObject given a data object.  Called from
     * DomainObjectFactory.newInstance() as the last step of
     * instantiation.
     *
     * @param dataObject The data object from which to construct a domain
     * object.
     *
     * @return A domain object for this data object.
     */
    protected abstract DomainObject doNewInstance(DataObject dataObject);

}
