Carbide.c++

com.nokia.carbide.cpp.epoc.engine.model
Interface IView<Model>

All Known Subinterfaces:
IBldInfView, IImageMakefileView, IMakefileView, IMMPView

public interface IView<Model>

The base interface for a filtered view onto a model.

It allows for transactions of changes to be applied back to the model's DOM.

Multiple views may hold changes at the same time (for instance, a dirty editor and a project change listener updating SOURCE statements).

The updating model follows the CVS model for handling simultaneous changes:

  • Client makes changes to View A
  • Client makes changes to View B
  • Client commits View A. The #commit() call will synchronize on the IOwnedModel instance and apply changes, updating the DOM and document. Other existing views are out-of-sync (since they reference a stale filtered DOM and may hold changes that no longer apply). Also, due to the model’s document being changed, any other existing views may have unsynchronized cached source ranges into the document. The latter issue is not fatal – any DOM can be rewritten from scratch to recover the “essential” source, but obviously, we want to avoid this where possible.
  • The model notifies listeners (IModelListener#modelUpdated) that changes have occurred. The views themselves are always listeners and are always notified before client listeners.
  • View A ignores notification its own changes
  • View B, since it has changes, marks itself “out of sync” (#isUnsynchronized()). This disallows any commits.
  • Client for View A ignores listener for changes on its own view, if needed.
  • Client for View B periodically checks its synchronization state, or waits until it wants to commit. If out-of-sync on a commit, IllegalStateException is thrown. Finding it’s out of sync, the client decides whether to #revert() or #merge(). Usually it will #merge() to get an updated view combined with its current uncommitted changes. If its changes don’t merge cleanly, #merge() returns false. The listener may decide to show UI at this point. Only #revert(), a successful #merge(), or a #forceSynchronized() will clear the unsynchronized state and allow further writes.
  • Now both views are sync with the model.


    Method Summary
     void addListener(IViewListener listener)
              Add listener, ignore duplicates
     void commit()
              Commits changes to the underlying translation unit (visible from IOwnedModel#getTranslationUnit() and IView#getFilteredTranslationUnit()) When a view is committed, changes may or may not be made to the owning model's document.
     IPath convertModelToProjectPath(IPath prjPath)
              Convert a model-relative path to an project-relative path.
     IPath convertProjectToModelPath(IPath prjPath)
              Convert a project-relative path to an model-relative path.
     void dispose()
              Dispose view, removing its listeners and detaching it from model and losing any changes.
     void forceSynchronized()
              Forces view to be marked synchronized, a last resort if #merge() returns false and you don’t want to #revert().
     IData<IView<Model>> getData()
              Get a copy of cacheable data for the view.
     IMessage[] getMessages()
              Get all messages associated with parsing the filtered TU.
     Model getModel()
              Get the model we're viewing
     IPath getProjectPath()
              Get the project root from the view configuration.
     IPath[] getReferencedFiles()
              Get the array of filesystem paths for files read while creating the filtered translation units
     IViewConfiguration getViewConfiguration()
              Get the configuration used to create the view
     void markUnsynchronized()
              Mark a view out-of-sync due to changes in the model.
     boolean merge()
              Merges uncommitted changes with the current model.
     boolean needsSynchonize()
              Tell whether the view needs to be synchronized (merged) with the model.
     void removeListener(IViewListener listener)
              Remove listener, ignore if not present
     void revert()
              Reverts changes to mirror model contents and marks the view synchronized.
     void setDebug(boolean debug)
              Enable debugging, if supported.
     

    Method Detail

    getModel

    Model getModel()
    Get the model we're viewing


    dispose

    void dispose()
    Dispose view, removing its listeners and detaching it from model and losing any changes. All views must be disposed before the model can be disposed.


    getViewConfiguration

    IViewConfiguration getViewConfiguration()
    Get the configuration used to create the view

    Returns:
    configuration (never null)

    getMessages

    IMessage[] getMessages()
    Get all messages associated with parsing the filtered TU. This includes those from the problem nodes and additional diagnostics.

    Returns:
    array (never null)

    getReferencedFiles

    IPath[] getReferencedFiles()
    Get the array of filesystem paths for files read while creating the filtered translation units

    Returns:
    list of paths (never null)

    revert

    void revert()
    Reverts changes to mirror model contents and marks the view synchronized.


    commit

    void commit()
                throws java.lang.IllegalStateException
    Commits changes to the underlying translation unit (visible from IOwnedModel#getTranslationUnit() and IView#getFilteredTranslationUnit())

    When a view is committed, changes may or may not be made to the owning model's document. A document change event will be sent if the contents change, and that event will cause the model to mark any open views (except this one) unsynchronized.

    During a commit, the contents of the view may be recreated. Any references to objects provided by the view should be considered stale.

    A commit can throw IllegalStateException if it is unsynchronized. The code for a commit should be structured like this:

                    // commit changes
                    while (true) {
                            try { 
                                    view.commit();
                                    break;
                            } catch (IllegalStateException e) {  // happens when third party has committed in-between
                                    // usually UI around this...
                                    if (!view.merge()) {
                                            // worst case (could try view.forceSynchronized() too)
                                            view.revert();
                                    }
                                    // further failures should not occur, but loop just in case the
                                    // UI above took long enough for someone else to sneak in
                            }
                    }
             

    Throws:
    java.lang.IllegalStateException - if out of sync
    See Also:
    needsSynchonize(), merge(), revert()

    markUnsynchronized

    void markUnsynchronized()
    Mark a view out-of-sync due to changes in the model.

    See Also:
    needsSynchonize()

    needsSynchonize

    boolean needsSynchonize()
    Tell whether the view needs to be synchronized (merged) with the model.

    A newly created view never needs synchronization, and a view with changes does not necessarily need synchronization.

    Only when the model is changed underneath (e.g. other views commit, the DOM is changed directly, or the document is changed) and the view has uncommited changes and wants to commit is synchronization needed.

    Returns:
    true: view needs to be reverted or forced synchronized

    merge

    boolean merge()
    Merges uncommitted changes with the current model.

    Returns true if pending changes merge cleanly, with view left in synchronized state. Returns false otherwise, leaving view in a unsynchronized state, possibly with partial updates.

    Returns:
    merge succeeded
    See Also:
    needsSynchonize()

    forceSynchronized

    void forceSynchronized()
    Forces view to be marked synchronized, a last resort if #merge() returns false and you don’t want to #revert().


    addListener

    void addListener(IViewListener listener)
    Add listener, ignore duplicates


    removeListener

    void removeListener(IViewListener listener)
    Remove listener, ignore if not present


    getProjectPath

    IPath getProjectPath()
    Get the project root from the view configuration.

    Returns:
    IPath absolute path to project root

    setDebug

    void setDebug(boolean debug)
    Enable debugging, if supported. Dumps information to System.out.

    Parameters:
    debug - true to debug, false to stop

    convertProjectToModelPath

    IPath convertProjectToModelPath(IPath prjPath)
    Convert a project-relative path to an model-relative path.

    Null or full paths returned as identity.

    Parameters:
    prjPath - project-relative path (or null or full path)
    Returns:
    path adjusted to be model-relative (except for null or full path which are returned the same)

    convertModelToProjectPath

    IPath convertModelToProjectPath(IPath prjPath)
    Convert a model-relative path to an project-relative path.

    Null or full paths returned as identity.

    Parameters:
    modelPath - model-relative path (or null or full path)
    Returns:
    path adjusted to be project-relative (except for null or full path which are returned the same)

    getData

    IData<IView<Model>> getData()
    Get a copy of cacheable data for the view.

    Returns:
    instance of IData containing current data in the view, or null if such data cannot be created

    Carbide.c++