DesignHistory Code Samples

This section contains sample code for Design History. More...

This section contains sample code for Design History.

Initialize design history in a file

    #include <DgnPlatform/DesignHistory.h>

    USING_NAMESPACE_BENTLEY
    USING_NAMESPACE_BENTLEY_MSTNPLATFORM
    USING_NAMESPACE_BENTLEY_MSTNPLATFORM_ELEMENT
    USING_NAMESPACE_DGNPLATFORM_DGNHISTORY

    StatusInt    initializeHistory (RevisionNumber& initialRevision, DgnFileR file)
        {
        if (!DesignHistory::ContainsHistory (file))
            {
            StatusInt s = DesignHistory::InitializeHistory (file, L"My first revision");
            if (SUCCESS != s)
                return s;
            }

        DesignHistory history (file);
        initialRevision = history.GetTip ();
        return SUCCESS;
        }
See also
Bentley::DgnPlatform::DgnHistory::DesignHistory::ContainsHistory
Bentley::DgnPlatform::DgnHistory::DesignHistory::InitializeHistory
Bentley::DgnPlatform::DgnHistory::DesignHistory::GetTip

Save recent changes in design history.

This is called a "commit."

        DesignHistory history (file);
        RevisionInfo revInfo;
        StatusInt s = history.Commit (&revInfo, CommitInfo (L"description of the changes"));
        if (SUCCESS != s)
            return s;
        // revInfo.m_num is the number of the newly created revision
See also
Bentley::DgnPlatform::DgnHistory::DesignHistory::Commit

List all changes since a given revision

    void    listChangesSince (DgnFileR file, RevisionNumber const& savedRevision)
        {
        StatusInt s;

        DesignHistory history (file);

        //  Get the list of revision numbers that have been created since the saved revision number, including "Recent" changes.
        RevisionNumbersForFile revs;
        s = history.GetRevisionNumbers (revs, savedRevision, RevisionNumber::Recent());
        if (SUCCESS != s)
            return; // ERROR!

        //  Get the elements changed in this range of revisions (including "Recent")
        //  This query gets the post-change state of the elements. Call QueryPreChangeState to get the pre-change states.
        RefCountedPtr<ElementsAsOfQuery> changedElements = history.QueryPostChangeState (revs);
        if (changedElements == NULL)
            return; // ERROR!

        //  Show each element ...
        for each (ElementQueryResultsForModel const& modelResult in *changedElements)
            {
            for each (ElementQueryResult const& elementResult in modelResult)
                {
                MSElementDescrCP ed = elementResult.GetElement (); // this is the post-change state - will always be non-NULL, even for deletes
                ElementChangeType ct = elementResult.GetChangeType ();
                printf ("change=%d element id=%llu type=%d\n", ct, ed->el.ehdr.uniqueId, ed->el.ehdr.type);
                }
            }
        }
See also
Bentley::DgnPlatform::DgnHistory::DesignHistory::GetRevisionNumbers
Bentley::DgnPlatform::DgnHistory::DesignHistory::QueryPostChangeState
Bentley::DgnPlatform::DgnHistory::ElementsAsOfQuery
Bentley::DgnPlatform::DgnHistory::ElementQueryResultsForModel
Bentley::DgnPlatform::DgnHistory::ElementQueryResult
Bentley::DgnPlatform::DgnHistory::ElementChangeType

In what revisions was a particular element changed?

    ModelId        mid = ... id of model that contains the element ...
    ElementId      eid = ... id of the element ...

    //  Get the revision numbers in the range that we care about. In this case, we get them all.
    DesignHistory dh (file);
    RevisionNumbersForFile rnf;
    dh.GetRevisionNumbers (rnf, RevisionNumber(), RevisionNumber(), true, false, false);

    //  Set up a filter that will focus the revision query on just the specified element.
    ElementChangeRecordFilter   justThisElement;
    justThisElement.m_elements.InsertElementIfNew (mid, eid);

    //  Set up a callback object to capture the number of the revision which the element is found
    T_RevisionInfoVector revs;
    dh.GetRevisions (revs, rnf, &justConflictElement, true);
    revs.front() is the earliest revision that changed the element
    revs.back () is the most recent revision that changed the element
See also
Bentley::DgnPlatform::DgnHistory::DesignHistory::GetRevisionNumbers
Bentley::DgnPlatform::DgnHistory::DesignHistory::GetRevisions
Bentley::DgnPlatform::DgnHistory::ElementChangeRecordFilter

Get version of element as of a given revision.

    RevisionNumber rev = ... the revision...
    ModelId        mid = ... id of model that contains the element ...
    ElementId      eid = ... id of the element ...

    DesignHistory dh (file);
    EditElementHandle historicalState;
    dh.QueryElementAsOf (historicalState, mid, eid, rev);
See also
Bentley::DgnPlatform::DgnHistory::RevisionNumbersForFile
Bentley::DgnPlatform::DgnHistory::ElementChangeRecordFilter
Bentley::DgnPlatform::DgnHistory::ElementsAsOfQuery
Bentley::DgnPlatform::DgnHistory::ElementQueryResult

Restore the contents of a file to a historical state

Design History Restore modifies a file in order to make the elements in that file match a selected historical state. To do this, Design History reads the information stored in history revisions and uses this information to decide with elements in the file must be deleted, modified, or recreated. To modify or recreate an element, Design History restore copies a saved image of the element from a revision into the file that is to be restored.

Note that DesignHistoryRestore actually produces a new state in the target file. That contents of the new state just happen to match the contents of the selected historical state. If you were to call DesignHistory Commit after restoring a revision, you would create a new revision in the file.

        #include <DgnPlatform/DesignHistoryRestore.h>

        DgnFileR dgnFile = ...  // the file to be modified. Must contain design history
        RevisionNumber targetRevision = ... // the point in history

        DesignHistoryRestore dr;
        StatusInt status = dr.Restore (dgnFile, targetRevision);

It usually makes more sense to use a tag to identify a point in history, rather than a raw revision number.

        #include <DgnPlatform/DesignHistoryRestore.h>

        DgnFileR dgnFile = ...  // the file to be modified. Must contain design history
        WChar const* tag = ... // tag identifying the desired point in history

        RevisionNumber targetRevision;  // find out what tag means in this file
        DesignHistory history (refFile);
        if (history.GetTag (&targetRevision, tag) != SUCCESS)
            {
            can't restore this one...
            return;
            }

        DesignHistoryRestore dr;
        StatusInt status = dr.Restore (dgnFile, targetRevision);
See also
Bentley::DgnPlatform::DgnHistory::DesignHistory
Bentley::DgnPlatform::DgnHistory::DesignHistoryRestore

Restoring reference attachments to a specified tag.

Design history is file-specific. As a result, restoring a file will not cause its reference attachments to be restored. If you want to restore the references of a file, you must apply DesignHistoryRestore to each referenced file. To do that, you must iterate the ModelRefs of the parent file, compile a unique set if of reference files, and apply DesignHistoryRestore to each file in turn.

    #include <DgnPlatform/DesignHistoryRestore.h>

    WChar const* tag = ... // tag identifying the rollback point in history in all files

    DgnModelRefP masterModelRef = ... // the model that references the other files to be restored

    bset<DgnFileP>  filesRestored; // keep track of the reference files that we've restored as we go along.

    ModelRefIteratorP   iterator;
    DgnModelRefP        refModelRef;

    mdlModelRefIterator_create (&iterator, masterModelRef, MRITERATE_PrimaryChildRefs|MRITERATE_ExtendedChildRefs, 99); // walk through all references, including nested references

    while (NULL != (refModelRef = mdlModelRefIterator_getNext (iterator)))
        {
        DgnFileP refFile = mdlModelRef_getDgnFile (refModelRef);

        if (!filesRestored.insert (refFile).second)
            continue;

        RevisionNumber targetRevision;        // find out what tag means in this file
        DesignHistory history (refFile);
        if (history.GetTag (&targetRevision, tag) != SUCCESS)
            {
            can't restore this one...
            continue;
            }

        DesignHistoryRestore dr;
        StatusInt status = dr.Restore (*refFile, targetRevision);
        if (SUCCESS != status)
            {
            restore failed ...
            continue;
            }

        //  Important! Once we modify a referenced model, it is no longer an image of what's on disk and is therefore no longer shareable.
        DgnFile::DgnModelIterator c (refFile);
        for each (DgnModelP loadedCache in refFile->LoadedModelsCollection ())
            loadedCache->SetIsFileImage (false);
        }


    mdlModelRefIterator_free (&iterator);
See also
Bentley::DgnPlatform::DgnHistory::DesignHistoryRestore

Copyright © 2017 Bentley Systems, Incorporated. All rights reserved.