com.architexa.diagrams.relo.jdt.parts.CompartmentedCodeUnitEditPart.java Source code

Java tutorial

Introduction

Here is the source code for com.architexa.diagrams.relo.jdt.parts.CompartmentedCodeUnitEditPart.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 Jun 13, 2004
 *
 */
package com.architexa.diagrams.relo.jdt.parts;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
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.CollectionUtils;
import org.apache.commons.collections.Transformer;
import org.apache.log4j.Logger;
import org.eclipse.swt.graphics.Color;
import org.openrdf.model.Resource;

import com.architexa.diagrams.draw2d.NonEmptyFigureSupport;
import com.architexa.diagrams.jdt.model.UserCreatedFragment;
import com.architexa.diagrams.model.ArtifactFragment;
import com.architexa.diagrams.model.ColorDPolicy;
import com.architexa.diagrams.model.DerivedArtifact;
import com.architexa.diagrams.relo.figures.CodeUnitFigure;
import com.architexa.diagrams.relo.jdt.ReloJDTPlugin;
import com.architexa.diagrams.relo.modelBridge.ControllerDerivedAF;
import com.architexa.diagrams.relo.parts.ArtifactEditPart;
import com.architexa.diagrams.relo.parts.MoreItemsEditPart;
import com.architexa.org.eclipse.draw2d.IFigure;
import com.architexa.org.eclipse.gef.EditPart;

/**
 * This class should really be able to go up higher in the chain, however, we
 * don't have multiple inheritance (and we need CodeUnitEditPart functionality)
 * so we are putting it after CodeUnitEditPart
 * 
 * @author vineet
 */
public abstract class CompartmentedCodeUnitEditPart extends CodeUnitEditPart {
    static final Logger logger = ReloJDTPlugin.getLogger(CompartmentedCodeUnitEditPart.class);

    public static abstract class CompartmentCodeUnit extends ControllerDerivedAF {
        public CompartmentCodeUnit(ArtifactFragment af) {
            super(af.getArt());
        }

        public abstract void registerTypes(Map<Resource, CompartmentCodeUnit> compartmentMap);
    }

    public static abstract class CompartmentCUEditPart extends MoreItemsEditPart {
        @Override
        public List<ArtifactFragment> getModelChildren() {
            CompartmentCodeUnit myCCU = (CompartmentCodeUnit) this.getModel();
            Map<Resource, CompartmentCodeUnit> parentCompartmentMap = ((CompartmentedCodeUnitEditPart) this
                    .getParent()).compartmentMap;
            Set<Resource> tgtTypes = new HashSet<Resource>(parentCompartmentMap.size());

            // get all types that the compartment applies to
            for (Map.Entry<Resource, CompartmentCodeUnit> compartmentMapEntry : parentCompartmentMap.entrySet()) {
                if (!compartmentMapEntry.getValue().equals(myCCU))
                    continue;
                tgtTypes.add(compartmentMapEntry.getKey());
            }

            // add all children of gotten types to the return
            ArtifactFragment compartmentedCU = ((CompartmentedCodeUnitEditPart) this.getParent()).getArtifact();
            List<ArtifactFragment> possChildren = compartmentedCU.getShownChildren();
            List<ArtifactFragment> retChildren = new ArrayList<ArtifactFragment>();
            for (ArtifactFragment possChildAF : possChildren) {
                if (possChildAF instanceof DerivedArtifact)
                    continue;
                //User Created
                if (possChildAF instanceof UserCreatedFragment
                        && tgtTypes.contains(((UserCreatedFragment) possChildAF).queryType(getRepo())))
                    retChildren.add(possChildAF);
                else if (tgtTypes.contains(possChildAF.getArt().queryType(possChildAF.getRootArt().getRepo())))
                    retChildren.add(possChildAF);
            }
            return retChildren;
        }
    }

    // detail level
    final int labelWithCompartments = getMinimalDL();

    /* (non-Javadoc)
     * @see com.architexa.diagrams.relo.parts.ArtifactEditPart#getDLStr(int)
     */
    @Override
    public String getDLStr(int dl) {
        if (dl == labelWithCompartments)
            return "labelWithCompartments";
        return super.getDLStr(dl);
    }

    @Override
    protected void updateMembers(int newDL) {
        if (newDL >= currDL) {
            if (newDL >= labelWithCompartments)
                realizeCompartments();
        }
        if (newDL < currDL) {
            if (newDL == labelWithCompartments) {
                emptyCompartments();
            } else if (newDL < labelWithCompartments) {
                hideCompartments();
            }
        }
    }

    // in the below we only store ComparmentTypes, each of which can support
    // one or more types of Artifacts, note the order in compartmentTypes matters
    List<Resource> compartmentTypes = new ArrayList<Resource>(5);

    public abstract CompartmentCodeUnit generateCompartment(Resource compartmentType,
            ArtifactFragment compartmentParent);

    Map<Resource, CompartmentCodeUnit> compartmentMap = new HashMap<Resource, CompartmentCodeUnit>(5);

    private CompartmentCodeUnit getCompartmentForType(Resource compartmentType) {
        CompartmentCodeUnit compartmentTypeCCU = compartmentMap.get(compartmentType);
        return compartmentTypeCCU;
    }

    private CompartmentCUEditPart getCompartmentEPForType(Resource compartmentType) {
        CompartmentCodeUnit compartmentCU = getCompartmentForType(compartmentType);
        if (compartmentCU != null)
            return (CompartmentCUEditPart) this.findEditPart(compartmentCU);
        return null;
    }

    // this is called by getModelChildren ... it can't depend on EP structure
    // because this is called during refresh to create the EP structure! ...and
    // if we depend on EP structure, GEF thinks that the model has no elements
    // ... hmm... shouldn't this just be a model accessor? ... perhaps this is
    // the cause of the problem
    protected List<CompartmentCodeUnit> getComparments() {
        // we can have repeats, but order matters
        List<CompartmentCodeUnit> retVal = new ArrayList<CompartmentCodeUnit>(compartmentMap.size());
        for (Resource compartmentType : compartmentTypes) {
            CompartmentCodeUnit compartmentTypeContainer = getCompartmentForType(compartmentType);
            if (compartmentTypeContainer != null && !retVal.contains(compartmentTypeContainer))
                retVal.add(compartmentTypeContainer);
        }
        return retVal;
    }

    protected void realizeCompartments() {
        try {
            for (Resource compartmentType : compartmentTypes) {
                CompartmentCUEditPart compartmentEP = getCompartmentEPForType(compartmentType);
                if (compartmentEP == null) {
                    compartmentEP = realizeCompartment(compartmentType);
                } else if (!this.getChildren().contains(compartmentEP)) {
                    // it was realized but has since been removed
                    logger.error("Should not happen");
                } else {
                    // already been realized...
                }
            }
        } catch (Throwable e) {
            logger.error("Unexpected exception", e);
        }
    }

    public void colorFigure(Color color) {
    }

    private CompartmentCUEditPart realizeCompartment(Resource compartmentType) {
        // create the compartments
        final CompartmentCodeUnit ccu = generateCompartment(compartmentType, getCU());
        ccu.registerTypes(compartmentMap);

        // install any needed policies
        ArtifactFragment compAF = getRootController().getRootArtifact().getArtifact(ccu);

        // initialize the compartments
        getArtifact().addPropertyChangeListener(new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent evt) {
                ccu.firePropChang(evt.getPropertyName());
                String propName = evt.getPropertyName();
                if (ArtifactFragment.Policy_Contents_Changed.equals(propName)) {
                    colorFigure(ColorDPolicy.getColor(getCU()));
                }
            }
        });

        // update children
        this.refreshChildren();

        CompartmentCUEditPart cep = (CompartmentCUEditPart) getRootController().findArtifactEditPart(compAF);

        final IFigure classFigure = (IFigure) CompartmentedCodeUnitEditPart.super.getFigure().getChildren().get(0);
        if (classFigure != null)
            NonEmptyFigureSupport.listenToModel(getArtFrag(), ((CodeUnitFigure) classFigure).nonEmptyFigure);
        return cep;
    }

    protected void hideCompartments() {
        getModelChildren().clear();
        refresh();
    }

    protected void emptyCompartments() {
        List<EditPart> visChildren = getVisibleEditPartChildren();
        List<Object> txVisChildren = new ArrayList<Object>(visChildren);
        CollectionUtils.transform(txVisChildren, new Transformer() {
            public Object transform(Object input) {
                if (input instanceof ArtifactEditPart) {
                    return ((ArtifactEditPart) input).getArtifact();
                } else
                    return null;
            }
        });
        removeChildrenArtifacts(txVisChildren);
    }

    @Override
    protected List<EditPart> getVisibleEditPartChildren() {
        List<EditPart> childrenEP = new ArrayList<EditPart>(20);
        // use hashset since the map can 
        for (CompartmentCodeUnit ccu : getComparments()) {
            CompartmentCUEditPart cep = (CompartmentCUEditPart) this.findEditPart(ccu);
            childrenEP.addAll(cep.getChildrenAsTypedList());
        }
        return childrenEP;
    }

    @Override
    public List<ArtifactFragment> getModelChildren() {
        return new ArrayList<ArtifactFragment>(getComparments());
    }

}