
//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 2007-2009 by Autodesk, Inc. 
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted, 
// provided that the above copyright notice appears in all copies and 
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting 
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC. 
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to 
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
// CREATED BY: Jiri Kripac                                 March 2007
//
// DESCRIPTION:
//
// AcDbAssocPersSubentId pure virtual base class.
//
//////////////////////////////////////////////////////////////////////////////

#pragma once
#include "acdb.h"
#pragma pack (push, 8)


/// <summary> <para>
/// Abstract base class used to persistently identify an AcDbSubentId of an 
/// AcDbEntity. Unlike AcDbSubentId that is transient and may change when the 
/// entity is modified, reevaluated, or similar, the AcDbAssocPersSubentId 
/// identifies the subentity in such a way that it is always possible to obtain 
/// the corresponding subentities (if they still exist), even after the entity 
/// has been edited or reevaluated any number of times.
/// </para> <para>
/// The base AcDbAssocPersSubentId class is an abstract base class. Concrete 
/// AcDbEntity classes need their own way how to represent a persistent 
/// identitfication of their subentities. Therefore there are derived 
/// AcDbAssocPersSubentId classes that keep the persistent identitifcation of
/// the subentities of particular entity types. The simplest one is the
/// AcDbAssocSimplePersSubentId derived class that just keeps the AcDbSubentId 
/// in case it can be relied on that it does not change.
/// </para> <para>
/// The AcRx protocol extension classes derived from AcDbAssocPersSubentIdPE
/// base class provide mapping from transient AcDbSubentId to the persistent
/// AcDbAssocPersSubentId, they allow to create new AcDbAssocPersSubentIds from
/// given AcDbSubentIds. The AcDbAssocPersSubentId provides mapping in the 
/// opposite direction, from AcDbAssocPersSubentIds to AcDbSubentIds.
/// </para> </summary>
///
class ACDB_PORT AcDbAssocPersSubentId : public AcRxObject
{
public:

	ACRX_DECLARE_MEMBERS(AcDbAssocPersSubentId);

    /// <summary> Default constructor. </summary>
    AcDbAssocPersSubentId() {}

    /// <summary> Virtual destructor. </summary>
    virtual ~AcDbAssocPersSubentId() {}

    /// <summary> <para>
    /// Mapping: AcDbAssocPersSubentId --> AcDbSubentId(s)
    /// </para> <para>
    /// Obtains all AcDbSubentIds corresponding to this AcDbAssocPersSubentId.
    /// </para> </summary>
    /// <remarks>
    /// Notice that one AcDbAssocPersSubentId may correspond to none, one or more than
    /// one AcDbSubentId, because the entity may have changed and there may not be 
    /// just a single subentity corresponding to the original subentity identified 
    /// by this AcDbAssocPersSubentId. The default implementation just calls the
    /// AcDbAssocPersSubentIdPE::getTransientSubentIds() method.
    /// </remarks>
    /// <param  name="pEntity"> The entity needs to be open for read. </param>
    /// <param  name="subents"> The returned AcDbSubentIds. </param>
    /// <returns> Acad::ErrorStatus. </returns>
    ///
    virtual Acad::ErrorStatus getTransientSubentIds(const AcDbEntity*      pEntity, 
                                                    AcArray<AcDbSubentId>& subents) const;


    /// <summary> Returns the type of the subentity. </summary>
    /// <param  name="pEntity"> The entity needs to be open for read. </param>
    /// <returns> AcDb::SubentType. </returns>
    ///
    virtual AcDb::SubentType subentType(const AcDbEntity* pEntity) const = NULL;

    /// <summary> 
    /// Returns the number of transient AcDbSubentIds corresponding to this 
    /// AcDbAssocPersSubentId. The default implementation just calls 
    /// getTransientSubentIds() and returns their count which usually is 1.
    /// </summary>
    /// <param  name="pEntity"> The entity needs to be open for read. </param>
    /// <returns> 
    /// Number of transient AcDbSubentIds corresponding to this AcDbAssocPersSubentId. 
    /// </returns>
    ///
    virtual int transientSubentCount(const AcDbEntity* pEntity) const;

    /// <summary> 
    /// Returns true iff this AcDbAssocPersSubentId is null, i.e. not referencing
    /// and subentity of any entity. It is logically slightly different from when
    /// getTransientSubentIds() returns no AcDbSubentIds. In the latter case the
    /// AcDbAssocPersSubentId may reference some subentities, but they may have
    /// been deleted, changed, or similar. 
    /// </summary>
    /// <returns> True iff this AcDbAssocPersSubentId is null. </returns>
    ///
    virtual bool isNull() const = NULL;

    /// <summary>
    /// Returns true iff this and the other AcDbAssocPersSubentId reference
    /// exactly the same subentity of the same entity. The base class 
    /// implementation just checks whether the classes of this and of the other
    /// AcDbAssocPersSubentId are identical.
    /// </summary>
    /// <param  name="pEntity"> 
    /// The entity owning the subentities of this and the other AcDbAssocPersSubentId. 
    /// </param>
    /// <param  name="pOther"> The other AcDbAssocPersSubentId. </param>
    /// <returns> True iff this and the other AcDbAssocPersSubentId are equal. </returns>
    ///
    virtual bool isEqualTo(const AcDbEntity* pEntity, const AcDbAssocPersSubentId* pOther) const
    {
        return this == pOther || pEntity != NULL && pOther != NULL && isA() == pOther->isA();
    }

    /// <summary> <para>
    /// Notifies this AcDbAssocPersSubentId that the entity has been mirrored
    /// and that the AcDbAssocPersSubentId may possibly need to update itself
    /// to identify the same subentity in the mirrored entity as it identified
    /// before the entity has been mirrored.
    /// </para> <para>
    /// The default implementation obtains AcDbAssocPersSubentIdPE from the 
    /// mirrored entity and calls AcDbAssocPersSubentIdPE::mirrorPersSubent()
    /// that does all the work. By default the "work" is a no-op, except for
    /// some entity types, such as AcDbArc and its AcDbAssocArcPersSubentIdPE
    /// protocol extension class.
    /// </para> </summary>
    /// <param  name="pMirroredEntity"> 
    /// The entity that has been mirrored. It needs to be open for read.
    /// </param>
    /// <returns> Acad::ErrorStatus. </returns>
    ///
    virtual Acad::ErrorStatus mirror(const AcDbEntity* pMirroredEntity);

    /// <summary>
    /// A static method that reads the class identification of the actual 
    /// AcDbAssocPersSubentId-derived class, creates an object of this derived
    /// class and calls dwgInFields() on it.
    /// </summary>
    /// <param  name="pFiler"> 
    /// The filer to read the data from. The first data is the class identification.
    /// </param>
    /// <param  name="pCreatedPersSubentId"> 
    /// This is an in/out argument used to return the created and filled-in object 
    /// of an AcDbAssocPersSubentId-derived class. If the pCreatedPersSubentId 
    /// is passed in as not NULL, the code tries to reuse the existing object, 
    /// if it is of the expected derived class. If it is passed in as NULL or 
    /// is not of the expected derived type, it creates a new object (deleting 
    /// the existing one, if any).
    /// /// </param>
    /// <returns> Acad::ErrorStatus. </returns>
    //
    static Acad::ErrorStatus 
    createObjectAndDwgInFields(AcDbDwgFiler*           pFiler, 
                               AcDbAssocPersSubentId*& pCreatedPersSubentId);

    /// <summary>
    /// A static method that reads the class identification of the actual 
    /// AcDbAssocPersSubentId-derived class, creates an object of this derived
    /// class and calls dxfInFields() on it.
    /// </summary>
    /// <param  name="pFiler"> 
    /// The filer to read the data from. The first data is the class identification.
    /// </param>
    /// <param  name="pCreatedPersSubentId"> 
    /// This is an in/out argument used to return the created and filled-in object 
    /// of an AcDbAssocPersSubentId-derived class. If the pCreatedPersSubentId 
    /// is passed in as not NULL, the code tries to reuse the existing object, 
    /// if it is of the expected derived class. If it is passed in as NULL or 
    /// is not of the expected derived type, it creates a new object (deleting 
    /// the existing one, if any).
    /// /// </param>
    /// <returns> Acad::ErrorStatus. </returns>
    //
    static Acad::ErrorStatus 
    createObjectAndDxfInFields(AcDbDxfFiler*           pFiler, 
                               AcDbAssocPersSubentId*& pCreatedPersSubentId);

    /// <summary>
    /// The standard filing protocol. The AcDbAssocPersSubentId base class
    /// implementation writes-out the actual class identification so that 
    /// it is possible to create an object of the same class when the data is 
    /// read back in (this happens in createObjectAndDwgInFields()).
    /// </summary>
    /// <param  name="pFiler"> The filer to write the object data to. </param>
    /// <returns> Acad::ErrorStatus. </returns>
    ///
    virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* pFiler) const;

    /// <summary>
    /// The standard filing protocol. The AcDbAssocPersSubentId base class
    /// implementation does nothing and doesn't therefore need to be called
    /// from the derived classes.
    /// </summary>
    /// <param  name="pFiler"> The filer to read the object data from. </param>
    /// <returns> Acad::ErrorStatus. </returns>
    ///
    virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* pFiler);

    /// <summary>
    /// The standard filing protocol. The AcDbAssocPersSubentId base class
    /// implementation writes-out the actual class identification so that 
    /// it is possible to create an object of the same class when the data is 
    /// read back in (this happens in createObjectAndDxfInFields()).
    /// </summary>
    /// <param  name="pFiler"> The filer to write the object data to. </param>
    /// <returns> Acad::ErrorStatus. </returns>
    ///
    virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFiler* pFiler) const;

    /// <summary>
    /// The standard filing protocol. The AcDbAssocPersSubentId base class
    /// implementation does nothing and doesn't therefore need to be called 
    /// from the derived classes.
    /// </summary>
    /// <param  name="pFiler"> The filer to read the object data from. </param>
    /// <returns> Acad::ErrorStatus. </returns>
    ///
    virtual Acad::ErrorStatus dxfInFields(AcDbDxfFiler* pFiler);

    /// <summary> The standard protocol. </summary>
    /// <param  name="pAuditInfo"> See the AcDbAuditInfo documentation. </param>
    /// <returns> Acad::ErrorStatus. </returns>
    ///
    virtual Acad::ErrorStatus audit(AcDbAuditInfo* pAuditInfo) { return Acad::eOk; }

}; // class AcDbAssocPersSubentId


#pragma pack (pop)


