Acad::ErrorStatus
ArxDbgDbEntity::wblockClone(AcRxObject* pOwner, AcDbObject*& pClone,
                    AcDbIdMapping& idMap, Adesk::Boolean isPrimary) const
{
	if (ArxDbgOptions::m_instance.m_showWblockCloneDetails) {
		CString titleStr, tmpStr;
		titleStr.Format(_T("Beginning -- wblockClone: %s"),
				ArxDbgUtils::objToClassAndHandleStr(const_cast<ArxDbgDbEntity*>(this), tmpStr));
		ArxDbgUiTdmIdMap dbox(&idMap, acedGetAcadDwgView(), titleStr);
		dbox.DoModal();
	}

    AcDb::DeepCloneType type = idMap.deepCloneContext();

        // if xrefInsert or xrefBind, we know everything will
        // be cloned, so just let normal routine handle this
    if ((type == AcDb::kDcXrefBind) || (type == AcDb::kDcXrefInsert)) {
        return AcDbEntity::wblockClone(pOwner, pClone, idMap, isPrimary);
    }
		// if we've already been cloned, just return
	AcDbIdPair idPair(objectId(), AcDbObjectId::kNull, true);
    if (idMap.compute(idPair) && (idPair.value() != AcDbObjectId::kNull)) {
        return Acad::eOk;
    }

        // If isPrimary is kTrue, then override the default cloning
        // within our own cloning, which would set it to kFalse,
        // by cloning our referenced entity first.
    if (isPrimary) {
			// now ask derived classes what references they want cloned for them
		AcDbObjectIdArray refEntIds;
		AcDbIntArray refTypes;
		getCloneReferences(type, refEntIds, refTypes);

		ASSERT(refEntIds.length() == refTypes.length());

            // clone each entity we reference first and change the value
            // of isPrimary to fake it out.  Since we clone these first,
            // when the normal wblockClone is called, it will see that
            // they are already in the set of cloned objects and will not
            // try to clone it again.
        AcDbEntity* ent;
        Acad::ErrorStatus es;
		int len = refEntIds.length();
		for (int i=0; i<len; i++) {
			if (refTypes[i] == kClone) {
				es = acdbOpenAcDbEntity(ent, refEntIds[i], AcDb::kForRead);
				if (es == Acad::eOk) {
						// this method only works if they come from the same block
						// (which SHOULD always be the case!)
					if (blockId() == ent->blockId()) {
							// Use the same owner, and pass in the same isPrimary value
						AcDbObject* pSubClone = NULL;
						es = ent->wblockClone(pOwner, pSubClone, idMap, Adesk::kTrue);
						if (pSubClone != NULL)
							pSubClone->close();

						if (es != Acad::eOk) {
							ASSERT(0);
						}
					}
					else {
						ASSERT(0);
					}

					ent->close();
				}
			}
		}
    }
        // Now we can clone ourselves via calling our parent's method.
	Acad::ErrorStatus es =  AcDbEntity::wblockClone(pOwner, pClone, idMap, isPrimary);

	if (ArxDbgOptions::m_instance.m_showWblockCloneDetails) {
		CString titleStr, tmpStr;
		titleStr.Format(_T("End -- wblockClone: %s"),
				ArxDbgUtils::objToClassAndHandleStr(const_cast<ArxDbgDbEntity*>(this), tmpStr));
		ArxDbgUiTdmIdMap dbox(&idMap, acedGetAcadDwgView(), titleStr);
		dbox.DoModal();
	}

	return es;
}
Acad::ErrorStatus
ArxDbgUtils::verifyEntityReference(const AcDbEntity* ent, const AcDbObjectId& idToValidate,
                 AcRxClass* classType, bool allowNull, bool allowErased)
{
    if (ent == NULL) {
        ASSERT(0);
        return Acad::eInvalidInput;
    }

        // first check for NULL
    if (idToValidate == AcDbObjectId::kNull) {
        if (allowNull)
            return Acad::eOk;
        else
            return Acad::eNullObjectId;
    }

        // now open it up and see what it is
    Acad::ErrorStatus es;
    AcDbEntity* entToValidate;
    es = acdbOpenAcDbEntity(entToValidate, idToValidate, AcDb::kForRead);
    if (es == Acad::eOk) {
            // make sure all references are from the same database
            // which should always be the case!
        if (ent->database() != entToValidate->database()) {
            entToValidate->close();
            return Acad::eWrongDatabase;
        }
            // make sure that references are from the same block
            // This can fail from a simple deepClone() to make a
            // blockTableRecord.  If the user didn't pick all the
            // referenced objects in the anchor at the time of
            // making the block, they will still point to the
            // entities in modelSpace... which will eventually crash
            // the whole thing.
        if (ent->blockId() != entToValidate->blockId()) {
            entToValidate->close();
            return Acad::eNotInBlock;
        }

            // see if they want to validate based on object type
        if (classType != NULL) {
            es = verifyClassType(entToValidate, classType);
            if (es != Acad::eOk) {
                entToValidate->close();
                return es;
            }
        }

        entToValidate->close();
        return Acad::eOk;               // passed our test    
    }
    else if (es == Acad::eWasErased) {
        if (allowErased)
            return Acad::eOk;           // passed under relaxed constraints
        else
            return Acad::eWasErased;    // failed
    }
    else {
        return es;                      // failed
    }
}