com.architexa.diagrams.relo.parts.ArtifactEditPart.java Source code

Java tutorial

Introduction

Here is the source code for com.architexa.diagrams.relo.parts.ArtifactEditPart.java

Source

/* 
 * Copyright (c) 2004-2005 Massachusetts Institute of Technology. This code was
 * developed as part of the Haystack (http://haystack.lcs.mit.edu/) research 
 * project at MIT. Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation files (the 
 * "Software"), to deal in the Software without restriction, including without 
 * limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom
 * the Software is furnished to do so, subject to the following conditions: 
 * 
 * The above copyright notice and this permission notice shall be included in 
 * all copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE. 
 */
/*
 * Created on Mar 4, 2005
 *
 */
package com.architexa.diagrams.relo.parts;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.Predicate;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.openrdf.model.Resource;
import org.openrdf.model.URI;

import com.architexa.diagrams.RSECore;
import com.architexa.diagrams.commands.AddNodeAndRelCmd;
import com.architexa.diagrams.model.Artifact;
import com.architexa.diagrams.model.ArtifactFragment;
import com.architexa.diagrams.model.ArtifactRel;
import com.architexa.diagrams.model.DerivedArtifact;
import com.architexa.diagrams.model.DirectedRel;
import com.architexa.diagrams.parts.ArtifactRelModificationEditPolicy;
import com.architexa.diagrams.parts.BasicRootController;
import com.architexa.diagrams.parts.NavAidsEditPart;
import com.architexa.diagrams.parts.NavAidsEditPolicy;
import com.architexa.diagrams.parts.NavAidsSpec;
import com.architexa.diagrams.relo.ReloPlugin;
import com.architexa.diagrams.relo.commands.ReparentCommand;
import com.architexa.diagrams.relo.commands.old.CreateParentCommand;
import com.architexa.diagrams.relo.modelBridge.JoinedRelType;
import com.architexa.diagrams.relo.modelBridge.ReloDoc;
import com.architexa.diagrams.ui.MultiAddCommandAction;
import com.architexa.intro.preferences.LibraryPreferences;
import com.architexa.org.eclipse.draw2d.Figure;
import com.architexa.org.eclipse.draw2d.IFigure;
import com.architexa.org.eclipse.gef.EditPart;
import com.architexa.org.eclipse.gef.commands.Command;
import com.architexa.org.eclipse.gef.commands.CompoundCommand;
import com.architexa.org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import com.architexa.store.ReloRdfRepository;

/**
 * Place for functionality that is essentially an RDF Controller/EditPart
 * @author vineet
 *
 */
public abstract class ArtifactEditPart extends AbstractReloEditPart
        implements PropertyChangeListener, NavAidsEditPart {
    static final Logger logger = ReloPlugin.getLogger(ArtifactEditPart.class);

    public ArtifactFragment getArtifact() {
        Object retVal = getModel();
        if (retVal instanceof ArtifactFragment) {
            return (ArtifactFragment) retVal;
        } else if (retVal instanceof Artifact) {
            // @tag examine-postRearch: need to re-enable code below and clean things up
            //logger.warn("Got Artifact expecting ArtifactFragment.", new Throwable());
            return new ArtifactFragment((Artifact) retVal);
        } else {
            logger.error("Expecting Artifact got: " + retVal.getClass(), new Throwable());
            return null;
        }
    }

    public ArtifactFragment getArtFrag() {
        return this.getArtifact();
    }

    @Override
    public ReloController getRootController() {
        return (ReloController) this.getRoot().getContents();
    }

    @Override
    public List<ArtifactFragment> getModelChildren() {
        return getArtifact().getShownChildren();
    }

    public void appendModelChild(ArtifactFragment child) {
        getArtifact().appendShownChild(child);
    }

    public boolean removeModelChild(Object child) {
        return getArtifact().removeShownChild(child);
    }

    public void clearModelChildren() {
        getArtifact().clearShownChildren();
    }

    public void addModelAndChild(ArtifactEditPart child) {
        addChild(child);
        appendModelChild(child.getArtifact());
    }

    // TODO: is this implemented correctly?
    public boolean removeChildInHeirarchy(EditPart child) {
        // support the fact that children may not be directly under the parent
        if (child.getParent() != this && child.getParent().getModel() instanceof DerivedArtifact)
            return ((ArtifactEditPart) child.getParent()).removeChildInHeirarchy(child);
        else {
            return removeModelChild(child.getModel());
        }
    }

    // TODO: is this implemented correctly?
    public static boolean removeArtFrag(ArtifactFragment childAF) {
        return childAF.getParentArt().removeShownChild(childAF);
    }

    @Override
    protected List<ArtifactRel> getModelSourceConnections() {
        return getArtifact().getShownSourceConnections();
    }

    @Override
    protected List<ArtifactRel> getModelTargetConnections() {
        return getArtifact().getShownTargetConnections();
    }

    // misc methods

    public List<AbstractGraphicalEditPart> getSelectedAGEP() {
        List<ArtifactEditPart> retList = this.getRootController().getSelectedArtifactEditParts();
        return new ArrayList<AbstractGraphicalEditPart>(retList);
    }

    public List<Artifact> listModel(ReloRdfRepository repo, DirectedRel rel, Predicate filter) {
        return this.getArtifact().getArt().queryArtList(repo, rel, filter);
    }

    public List<Artifact> showableListModel(ReloRdfRepository repo, DirectedRel rel, Predicate filter) {
        BasicRootController rc = getRootController();
        List<Artifact> filteredList = listModel(repo, rel, filter);

        for (Artifact relArt : new ArrayList<Artifact>(filteredList)) {
            if (!rc.canAddRel(getArtFrag(), rel, relArt))
                filteredList.remove(relArt);
        }
        return filteredList;
    }

    public Resource getElementRes() {
        return this.getArtifact().getArt().elementRes;
    }

    public String getRelModelLabel(Object model) {
        if (!(model instanceof Artifact))
            return "{err}";
        return ((Artifact) model).queryName(getRepo());
    }

    public List<NavAidsSpec> getSingleSelectHandlesSpecList(NavAidsEditPolicy policy) {
        return new ArrayList<NavAidsSpec>();
    }

    public List<NavAidsSpec> getMultiSelectHandlesSpecList(NavAidsEditPolicy policy) {
        return new ArrayList<NavAidsSpec>();
    }

    // Overridden by CodeUnitEditPart
    public IFigure getMoreButton() {
        return new Figure();
    }

    // Overridden by CodeUnitEditPart
    public void buildNavAidMenu(List<MultiAddCommandAction> menuActions, NavAidsSpec spec, IMenuManager defaultMenu,
            DirectedRel rel) {
    }

    @Override
    public void activate() {
        try {
            super.activate();
            this.getArtifact().addPropertyChangeListener(this);
        } catch (Throwable t) {
            logger.error("Unexpected Exception", t);
        }
    }

    @Override
    public void deactivate() {
        try {
            super.deactivate();
            this.getArtifact().removePropertyChangeListener(this);
        } catch (Throwable t) {
            logger.error("Unexpected Exception", t);
        }
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        this.refresh();
    }

    @Override
    protected void createEditPolicies() {
        super.createEditPolicies();
        installEditPolicy(ArtifactRelModificationEditPolicy.KEY, new ArtifactRelModificationEditPolicy());
    }

    /*
     * Detail level functionality
     */
    protected int currDL = getDefaultDL();

    public int getDetailLevel() {
        return currDL;
    }

    public int getMinimalDL() {
        return 0;
    }

    public int getDefaultDL() {
        return getMinimalDL();
    }

    public int getMaximumDL() {
        return getDefaultDL() + 1;
    }

    /**
      * Used for debugging purposes
     * @param dl
     * @return
     */
    public String getDLStr(int dl) {
        if (dl == getMinimalDL())
            return "minimalDL";
        else
            return "unknownDL";
    }

    public void suggestDetailLevelIncrease() {
        //logger.debug(this.getClass().getName() + ".suggestDetailLevelIncrease: " + getDLStr(currDL));
        if (currDL <= getMaximumDL()) {
            updateMembers(currDL + 1);
            currDL++;
        }
    }

    public void suggestDetailLevelDecrease() {
        //logger.debug(this.getClass().getName() + ".suggestDetailLevelDecrease: " + getDLStr(currDL));
        //ConsoleView.logCause(new Exception());
        if (currDL >= getMinimalDL()) {
            updateMembers(currDL - 1);
            currDL--;
        }
    }

    @Override
    protected IFigure createFigure() {
        //logger.debug("Creating figure for: " + this);

        if (getDefaultDL() - 1 < getMinimalDL()) {
            IFigure fig = createFigure(null, getMinimalDL());
            currDL = getMinimalDL();
            return fig;
        } else {
            IFigure fig = createFigure(null, getDefaultDL() - 1);
            currDL = getDefaultDL() - 1;
            return fig;
        }
    }

    // called to update to new detail level
    protected abstract IFigure createFigure(IFigure curFig, int newDL);

    protected void updateMembers(int newDL) {
        if (newDL > currDL && newDL > getMinimalDL())
            realizeChildrenArtifacts(getArtifact().getArt().queryChildrenArtifacts(getRepo()));
        if (newDL < currDL && newDL < getMaximumDL())
            removeChildrenArtifacts(getArtifact().getArt().queryChildrenArtifacts(getRepo()));
    }

    /*
     * other misc. functionality
     *
     */

    //TODO: review
    public void realizeChildrenArtifacts(List<Artifact> lst) {
        ReloController rc = (ReloController) getRoot().getContents();

        for (Artifact child : lst) {
            rc.getRootArtifact().addVisibleArt(child);
        }

    }

    public void removeChildrenArtifacts(Collection<?> lst) {
        //logger.debug("removeChildrenCUs: size: " + lst.size());
        for (Object child : lst) {
            AbstractGraphicalEditPart childEP = findEditPart(child);
            if (childEP != null)
                removeChildInHeirarchy(childEP);
        }

    }

    /**
      * Add menu items to only singly selected AEP's
      * 
      * TODO: find the likely better/official way to do this
     * @param menu
     */
    public void buildContextMenu(IMenuManager menu) {
    }

    public Action getRelAction(final String text, final DirectedRel rel, final Predicate filter) {
        return new Action(text) {
            @Override
            public void run() {
                final CompoundCommand actionCmd = new CompoundCommand();

                final IRunnableWithProgress op = new IRunnableWithProgress() {
                    public void run(final IProgressMonitor monitor)
                            throws InvocationTargetException, InterruptedException {
                        monitor.beginTask(text, IProgressMonitor.UNKNOWN);
                        Display.getDefault().asyncExec(new Runnable() {
                            public void run() {
                                ArtifactEditPart.this.showAllDirectRelation(actionCmd, rel, filter);
                                if (actionCmd.size() > 0)
                                    ArtifactEditPart.this.execute(actionCmd);
                            }
                        });
                    }
                };
                try {
                    new ProgressMonitorDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell())
                            .run(true, false, op);
                } catch (InvocationTargetException e) {
                    logger.error(e.getMessage());
                } catch (InterruptedException e) {
                    logger.error(e.getMessage());
                }
            }
        };
    }

    public Action getRelAction(final String text, final DirectedRel rel) {
        return getRelAction(text, rel, null);
    }

    // breakable needed in strata, so we must have it here
    public MultiAddCommandAction getShowRelAction(final BasicRootController rc, final DirectedRel rel,
            final Object relArt, final String relArtLbl) {
        return getShowRelAction(rc, rel, relArt, relArtLbl, true);
    }

    public MultiAddCommandAction getShowRelAction(final BasicRootController rc, final DirectedRel rel,
            final Object relArt, String relArtLbl, boolean breakable) {
        if (!(relArt instanceof Artifact))
            return null;
        MultiAddCommandAction action = new MultiAddCommandAction(relArtLbl, getRootController()) {
            @Override
            public Command getCommand(Map<Artifact, ArtifactFragment> addedArtToAFMap) {
                CompoundCommand tgtCmd = new CompoundCommand();
                AddNodeAndRelCmd addCmd = new AddNodeAndRelCmd(rc, getArtFrag(), rel, (Artifact) relArt,
                        addedArtToAFMap);
                tgtCmd.add(addCmd);
                if (addCmd.getNewParentArtFrag() != null)
                    ((ReloDoc) rc.getRootArtifact()).showIncludedRelationships(tgtCmd, addCmd.getNewArtFrag());
                return tgtCmd;
            }
        };

        // If relo preference set to only show lib code in
        // menus and not in diagram, disable the action
        if (!((Artifact) relArt).isInitialized(getRepo()) && LibraryPreferences.isReloLibCodeOnlyInMenu())
            action.setEnabled(false);

        return action;
    }

    public void buildMultipleSelectionContextMenu(IMenuManager menu) {
        // Do not add autoBrowse feature until better supported / documented

        //        IAction action = new Action("Autobrowse") {
        //            @SuppressWarnings("unchecked")
        //            @Override
        //            public void run() {
        //                final List<ArtifactEditPart> selEP = getViewer().getSelectedEditParts();
        //                CollectionUtils.filter(selEP, PredicateUtils.instanceofPredicate(ArtifactEditPart.class));
        //                if (selEP.size() < 2) return;
        //
        //                //PlatformUI.getWorkbench().getProgressService().runInUI()
        //                Job autoBrowseJob = new Job("Browsing graph") {
        //                    @Override
        //                    public IStatus run(IProgressMonitor monitor) {
        //                        autoBrowse(selEP, monitor);
        //                        return Status.OK_STATUS;
        //                    }
        //                };
        //                //autoBrowseJob.setSystem(true);
        //                autoBrowseJob.setUser(true);
        //                autoBrowseJob.setPriority(Job.INTERACTIVE);
        //                autoBrowseJob.schedule();
        //            }
        //        };

        // menu.appendToGroup("main", action);
    }

    // TODO: clean the threading/scheduling functionality here (may need UNDO support)
    private void autoBrowse(List<ArtifactEditPart> selEP, IProgressMonitor monitor) {
        for (ArtifactEditPart endEP : selEP) {
            for (ArtifactEditPart startEP : selEP) {
                // check start and end so that we call auto-browse only once
                if (endEP == startEP)
                    break;

                autoBrowse(startEP.getArtifact().getArt(), endEP.getArtifact().getArt(), 5, monitor);
            }
        }
    }

    protected void autoBrowse(Artifact startArt, Artifact endArt, int maxDepth, IProgressMonitor monitor) {
        logger.info("autoBrowsing: " + startArt + " // " + endArt);
        /*
        Pseudocode:
        1] let ptr=end
        2] ptrM1 = ptr-1
        3] get rel: ptr-?->ptrM1
        4] draw ptr-[rel]->ptrM1
        5] repeat till ptr=start
        */
        // draw from end-1
        Artifact ptr = endArt;
        while (!ptr.equals(startArt)) {
            logger.info("autoBrowsing - ptr: " + ptr);
            Artifact ptrM1 = breadthFirstSearch(startArt, ptr, maxDepth, monitor);
            if (ptrM1 == null)
                return;

            // draw links
            final Artifact currPtr = ptr;
            final Artifact currPtrM1 = ptrM1;
            PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
                public void run() {
                    try {
                        URI rel;

                        // forward
                        rel = getRepo().getStatement(currPtrM1.elementRes, (URI) null, currPtr.elementRes)
                                .getPredicate();
                        if (rel != null)
                            logger.info(currPtrM1 + " --" + rel + "--> " + currPtr);
                        if (rel != null && !rel.equals(RSECore.contains))
                            getRootController().addRel(currPtrM1, rel, currPtr);

                        // reverse
                        rel = getRepo().getStatement(currPtr.elementRes, (URI) null, currPtrM1.elementRes)
                                .getPredicate();
                        if (rel != null)
                            logger.info(currPtr + " --" + rel + "--> " + currPtrM1);
                        if (rel != null && !rel.equals(RSECore.contains))
                            getRootController().addRel(currPtr, rel, currPtrM1);
                    } catch (Exception e) {
                        logger.error("Unexpected error while creating drawing figures", e);
                    }
                }
            });

            ptr = ptrM1;
        }
    }

    /**
     * Does breadth first search and returns the Artifact corresponding to the 
     * shortest path (just before the end)
     * 
     * @param startArt
     * @param endArt
     * @return - Artifact corresponding to endArt-1
     */
    private Artifact breadthFirstSearch(Artifact startArt, Artifact endArt, int maxDepth,
            IProgressMonitor monitor) {
        /*
         * Pseudocode: 
         * 1] before loop, if source!=target put in queue, else return null 
         * 2] while queue !empty, i.e. the loop: 
         * 3] pop from queue, and get all connected, if !=target queue 
         * 4] else: return current, i.e. the step before the target
         */
        Set<URI> filteredPreds = getFilteredPredsForAutoBrowse();

        if (startArt.equals(endArt)) {
            logger.error("breadthFirstSearch should not be called with start==end", new Exception());
            return null;
        }

        // note: visible artifacts don't really matter for breadth-first search
        //  (and in reality for autobrowse)
        Set<Artifact> visitedArtifact = new HashSet<Artifact>(1000);

        List<Artifact> searchQueue = new ArrayList<Artifact>(100);
        searchQueue.add(startArt);

        // use null as a marker to indicate the completion of one level of depth
        searchQueue.add(null);

        int currDepth = 0;

        while (true) {
            Artifact searchNode = searchQueue.remove(0);
            if (searchNode == null) {
                currDepth++;
                if (currDepth >= maxDepth) {
                    logger.info("Graph not connected in depth: " + maxDepth);
                    return null;
                }
                if (searchQueue.isEmpty()) {
                    logger.info("Graph not connected");
                    return null;
                }
                monitor.worked(1);
                if (monitor.isCanceled())
                    return null;
                searchQueue.add(null);
                continue;
            }
            for (Artifact child : searchNode.queryConnectedArtifactsList(getRepo(), filteredPreds)) {
                if (child.equals(endArt))
                    return searchNode;
                if (visitedArtifact.contains(child))
                    continue;

                searchQueue.add(child);
                visitedArtifact.add(child);
            }
        }

    }

    protected Set<URI> getFilteredPredsForAutoBrowse() {
        Set<URI> filteredPreds = new HashSet<URI>();
        filteredPreds.add(getRepo().rdfType);
        filteredPreds.add(RSECore.contains);
        return filteredPreds;
    }

    public void showAllDirectRelation(CompoundCommand tgtCmd, final DirectedRel rel, Predicate filter) {
        try {
            ReloController rc = getRootController();
            Map<Artifact, ArtifactFragment> addedArtToAF = new HashMap<Artifact, ArtifactFragment>();
            for (final Artifact relCU : getArtifact().getArt().queryArtList(getRepo(), rel, filter)) {
                if (rc.canAddRel(getArtifact(), rel, relCU)) {
                    AddNodeAndRelCmd addCmd = new AddNodeAndRelCmd(rc, ArtifactEditPart.this.getArtFrag(), rel,
                            relCU, addedArtToAF);
                    tgtCmd.add(addCmd);
                    ((ReloDoc) rc.getRootArtifact()).showIncludedRelationships(tgtCmd, addCmd.getNewArtFrag());
                }
            }
        } catch (Throwable t) {
            logger.error("Unexpected exception", t);
        }
    }

    /**
     * Ensures that all elements on a valid path (given by rel) are shown
     * Note: src.rel.tgt && src!=tgt has to be true 
     * @param rel - join defining valid paths
     */
    public void showPathElements(JoinedRelType rel) {
        Artifact curArt = getArtifact().getArt();

        if (!isActive()) {
            log("not active");
            return;
        }

        logBeg("showPathElements");

        ReloController rc = getRootController();
        for (ArtifactEditPart visEP : rc.getVisibleNonDerivedArtifactEditParts()) {
            Artifact visArt = visEP.getArtifact().getArt();
            if (curArt.equals(visArt))
                continue;
            //ObjectPair examiningPair = new ObjectPair(this, visEP);

            for (List<Artifact> resultSetVar : rel.getPaths(getRepo(), curArt, visArt)) {
                for (Artifact resultArt : resultSetVar) {
                    rc.createOrFindArtifactEditPart(resultArt);
                }
            }

            // flip order of pair (everything else is identical
            for (List<Artifact> resultSetVar : rel.getPaths(getRepo(), visArt, curArt)) {
                for (Artifact resultArt : resultSetVar) {
                    rc.createOrFindArtifactEditPart(resultArt);
                }
            }
        }
        logEnd();
    }

    /**
     * Asserts parenthood for this AEP
     */
    public void assertParenthood() {
        CompoundCommand cc = new CompoundCommand();
        assertParenthood(cc);
        cc.execute();
    }

    /**
     * Asserts parenthood for this AEP
     */
    public void assertParenthood(CompoundCommand tgtCmd) {
        final ArtifactEditPart thisAEP = this;
        Artifact thisArt = thisAEP.getArtifact().getArt();
        ReloController rc = getRootController();

        //logger.info("assertParenthood: " + thisAEP);

        for (Artifact child : thisArt.queryChildrenArtifacts(thisAEP.getRepo())) {
            final ArtifactEditPart childEP = rc.findArtifactEditPart(child);
            if (childEP == null)
                continue;

            final ArtifactEditPart oldParentEP = (ArtifactEditPart) childEP.getParent();

            Command reparentCmd = new ReparentCommand(childEP, thisAEP, oldParentEP);

            if (oldParentEP instanceof ReloController) {
                // was at the top level before
                tgtCmd.add(reparentCmd);
                continue;
            }

            ArtifactEditPart oldParentAEP = (ArtifactEditPart) oldParentEP;

            // want to do: if (oldParentAEP == thisAEP) continue;
            //      need to do this otherwise we will have infinite loops 
            // we also need to take into account derived code units as well

            //@tag post-rearch-verify
            if (oldParentAEP.getArtifact().getNonDerivedBaseArtifact()
                    .equals(thisAEP.getArtifact().getNonDerivedBaseArtifact())) {
                continue;
            }

            tgtCmd.add(reparentCmd);
        }
    }

    public void realizeParent(CompoundCommand tgtCmd) {
        //logger.info("realizeParent: " + this);
        //logger.info(this.getClass().getName() + " .realizeParent() - parent: " + parent
        //        + " / findEditPart(parent): " + findEditPart(parent));

        if (getModel() instanceof DerivedArtifact)
            return;

        final Artifact parentArt = getArtifact().getArt().queryParentArtifact(getBrowseModel().getRepo());
        if (parentArt == null)
            return;

        final ReloController rc = getRootController();

        ArtifactEditPart parentEP = (ArtifactEditPart) findEditPart(parentArt);
        if (parentEP != null) {
            parentEP.assertParenthood(tgtCmd);
            return;
        }

        if (!rc.artCreatable(parentArt))
            return; // check if browse model will allow

        // parentEP = null and it is creatable

        tgtCmd.add(new CreateParentCommand(this, "create parent and assert parenthood", parentArt, rc));
        return;
    }

    public Resource getInstanceRes() {
        return getArtifact().getInstanceRes();
    }

    public void setInstanceRes(Resource viewRes) {
        getArtifact().setInstanceRes(viewRes);
    }

}