    001    package com.hammurapi.render.emf;
    002
    003    import java.io.File;
    004    import java.util.ArrayList;
    005    import java.util.Collection;
    006    import java.util.Collections;
    007    import java.util.Comparator;
    008    import java.util.List;
    009    import java.util.Locale;
    010    import java.util.Map;
    011    import java.util.concurrent.atomic.AtomicInteger;
    012
    013    import org.eclipse.emf.common.util.TreeIterator;
    014    import org.eclipse.emf.ecore.EAnnotation;
    015    import org.eclipse.emf.ecore.EClass;
    016    import org.eclipse.emf.ecore.EClassifier;
    017    import org.eclipse.emf.ecore.EDataType;
    018    import org.eclipse.emf.ecore.EModelElement;
    019    import org.eclipse.emf.ecore.ENamedElement;
    020    import org.eclipse.emf.ecore.EObject;
    021    import org.eclipse.emf.ecore.EPackage;
    022    import org.eclipse.emf.ecore.ETypedElement;
    023    import org.eclipse.gmf.runtime.notation.Diagram;
    024    import org.eclipse.gmf.runtime.notation.Node;
    025
    026    import com.hammurapi.common.Context;
    027    import com.hammurapi.common.IdentityManager;
    028    import com.hammurapi.render.RenderHelper;
    029
    030    /**
    031     * Helper class for rendering EMF model documentation.
    032     * @author Pavel Vlasov
    033     *
    034     */
    035    public class ModelRenderHelper extends RenderHelper {
    036
    037            private Map<EObject, List<Diagram>> diagramMap;
    038            private Model model;
    039
    040            /**
    041             * Constructor
    042             * @param identityManager IdentityManager.
    043             * @param outputDir Output directory.
    044             * @param diagramMap Maps diagram to a list of diagram elements.
    045             * @param model Model.
    046             * @param env Environment.
    047             * @param context Context.
    048             * @param locale Locale.
    049             */
    050            public ModelRenderHelper(
    051                            IdentityManager<?> identityManager,
    052                            File outputDir,
    053                            Map<EObject,
    054                            List<Diagram>> diagramMap,
    055                            Model model,
    056                            Map<String, Object> env,
    057                            Context context,
    058                            Locale locale,
    059                            boolean http) {
    060
    061                    super(identityManager, outputDir, env, context, locale, http);
    062                    this.diagramMap = diagramMap;
    063                    this.model = model;
    064            }
    065
    066            /**
    067             * @param obj
    068             * @return true if given model element contains sub-elements.
    069             */
    070            public boolean hasChildren(EObject obj) {
    071                    if (obj instanceof EPackage) {
    072                            EPackage pkg = (EPackage) obj;
    073                            List<Diagram> diagrams = diagramMap.get(pkg);
    074                            return !pkg.getESubpackages().isEmpty() || !pkg.getEClassifiers().isEmpty() || (diagrams!=null && !diagrams.isEmpty());
    075                    } else if (obj instanceof EClass) {
    076                            EClass cls = (EClass) obj;
    077                            return !cls.getEAttributes().isEmpty()
    078                            || !cls.getEOperations().isEmpty()
    079                            || !cls.getETypeParameters().isEmpty()
    080                            || !cls.getEReferences().isEmpty();
    081                    }
    082
    083                    return false; // For now
    084            }
    085
    086            /**
    087             * @param obj
    088             * @return List of diagrams in the model.
    089             */
    090            public List<Diagram> getDiagrams(EObject obj) {
    091                    List<Diagram> diagrams = diagramMap.get(obj);
    092                    if (diagrams==null) {
    093                            diagrams = Collections.emptyList();
    094                    }
    095
    096                    Collections.sort(diagrams, new Comparator<Diagram>() {
    097
    098                            @Override
    099                            public int compare(Diagram o1, Diagram o2) {
    100                                    if (o1==null) {
    101                                            return o2==null ? 0 : 1;
    102                                    }
    103
    104                                    if (o2==null) {
    105                                            return o1==null ? 0 : -1;
    106                                    }
    107
    108                                    String n1 = o1.getName();
    109                                    String n2 = o2.getName();
    110
    111                                    if (n1==null) {
    112                                            return n2==null ? 0 : 1;
    113                                    }
    114
    115                                    return n2==null ? -1 : n1.compareTo(n2);
    116                            }
    117
    118                    });
    119
    120                    return diagrams;
    121            }
    122
    123            /**
    124             * @param modelElement
    125             * @return Element documentation.
    126             */
    127            public String getDoc(EModelElement modelElement) {
    128                    EAnnotation genModel = modelElement.getEAnnotation("http://www.eclipse.org/emf/2002/GenModel");
    129                    if (genModel==null) {
    130                            return "";
    131                    }
    132                    return genModel.getDetails().get("documentation");
    133            }
    134
    135            /**
    136             * @param modelElement
    137             * @return First sentence from element documentation.
    138             */
    139            public String firstSentence(EModelElement modelElement) {
    140                    String ret = getDoc(modelElement);
    141                    int idx = ret.indexOf('.');
    142                    if (idx!=-1 && ret.length()>idx+1) {
    143                            ret = ret.substring(0, idx+1);
    144                    }
    145                    return ret;
    146            }
    147
    148            /**
    149             * @param pkg
    150             * @return List of classes in the package.
    151             */
    152            public List<EClass> classes(EPackage pkg) {
    153                    List<EClass> ret = new ArrayList<EClass>();
    154                    for (EClassifier c: pkg.getEClassifiers()) {
    155                            if (c instanceof EClass) {
    156                                    ret.add((EClass) c);
    157                            }
    158                    }
    159                    return sort(ret);
    160            }
    161
    162            /**
    163             * @param pkg
    164             * @return List of data types in the package.
    165             */
    166            public List<EDataType> dataTypes(EPackage pkg) {
    167                    List<EDataType> ret = new ArrayList<EDataType>();
    168                    for (EClassifier c: pkg.getEClassifiers()) {
    169                            if (c instanceof EDataType) {
    170                                    ret.add((EDataType) c);
    171                            }
    172                    }
    173                    return sort(ret);
    174            }
    175
    176            /**
    177             * @param modelElement
    178             * @return true  if model element is abstract.
    179             */
    180            public boolean isAbstract(EModelElement modelElement) {
    181                    return modelElement instanceof EClass && ((EClass) modelElement).isAbstract();
    182            }
    183
    184    //      static AtomicInteger counter = new AtomicInteger();
    185
    186            /**
    187             * Sorts model elements list by model element name.
    188             * @param <T>
    189             * @param list
    190             * @return
    191             */
    192            public <T extends ENamedElement> List<T> sort(List<T> list) {
    193    //              System.out.println(counter.getAndIncrement());
    194                    List<T> ret = new ArrayList<T>(list);
    195                    Collections.sort(ret, new Comparator<T>() {
    196
    197                            @Override
    198                            public int compare(T o1, T o2) {
    199                                    if (o1==null) {
    200                                            return o2==null ? 0 : 1;
    201                                    }
    202
    203                                    if (o2==null) {
    204                                            return o1==null ? 0 : -1;
    205                                    }
    206
    207                                    String n1 = o1.getName();
    208                                    String n2 = o2.getName();
    209
    210                                    if (n1==null) {
    211                                            return n2==null ? 0 : 1;
    212                                    }
    213
    214                                    return n2==null ? -1 : n1.compareTo(n2);
    215                            }
    216
    217                    });
    218                    return ret;
    219            }
    220
    221            /**
    222             * @param ete
    223             * @return bounds string.
    224             */
    225            public String bounds(ETypedElement ete) {
    226                    if (ete.getLowerBound()==ete.getUpperBound()) {
    227                            return String.valueOf(ete.getLowerBound());
    228                    }
    229
    230                    if (ete.getLowerBound()==0 && ete.getUpperBound()==-1) {
    231                            return "*";
    232                    }
    233
    234                    if (ete.getUpperBound()==-1) {
    235                            return ete.getLowerBound()+"..*";
    236                    }
    237
    238                    return ete.getLowerBound()+".."+ete.getUpperBound();
    239            }
    240
    241            /**
    242             * @param cls
    243             * @return List of direct subtypes of given type.
    244             */
    245            public List<EClass> getSubTypes(EClass cls) {
    246                    List<EClass> ret = new ArrayList<EClass>();
    247                    for (EObject rp: model.getRootPackages()) {
    248                            TreeIterator<EObject> rit = rp.eAllContents();
    249                            while (rit.hasNext()) {
    250                                    EObject obj = rit.next();
    251                                    if (obj instanceof EClass && ((EClass) obj).getESuperTypes().contains(cls)) {
    252                                            ret.add((EClass) obj);
    253                                    }
    254                            }
    255                    }
    256                    return ret;
    257            }
    258
    259            /**
    260             * @param cls
    261             * @return List of all (direct and indirect) subtypes of given type.
    262             */
    263            public List<EClass> getAllSubTypes(EClass cls) {
    264                    List<EClass> ret = new ArrayList<EClass>();
    265                    for (EObject rp: model.getRootPackages()) {
    266                            TreeIterator<EObject> rit = rp.eAllContents();
    267                            while (rit.hasNext()) {
    268                                    EObject obj = rit.next();
    269                                    if (obj instanceof EClass && ((EClass) obj).getEAllSuperTypes().contains(cls) && !ret.contains(obj)) {
    270                                            ret.add((EClass) obj);
    271                                    }
    272                            }
    273                    }
    274                    return ret;
    275            }
    276
    277            /**
    278             * @param diagram
    279             * @return Collection of diagram elements.
    280             * @throws Exception
    281             */
    282            public Collection<EObject> getDiagramElements(Diagram diagram) throws Exception {
    283                    List<EObject> diagramElements = new ArrayList<EObject>();
    284                    for (Object o: diagram.getChildren()) {
    285                            if (o instanceof Node) {
    286                                    EObject de = ((Node) o).getElement();
    287                                    if (de!=null) {
    288                                            if (de instanceof ENamedElement && ((ENamedElement) de).getName()!=null) {
    289                                                    diagramElements.add(de);
    290                                            }
    291                                    }
    292                            }
    293                    }
    294                    return diagramElements;
    295            }
    296
    297    //  It is very hard to make it work standalone. It is kept here for the future
    298    //  implementations when it is invoked from Eclipse UI.
    299    //      public void copyDiagramToImageFile(Diagram diagram) throws CoreException {
    300    //              CopyToImageUtil ctiu = new CopyToImageUtil();
    301    //              ImageFileFormat format = ImageFileFormat.GIF;
    302    //              IPath destination = new Path(new File(getOutputDir(), getId(diagram)+".gif").getAbsolutePath());
    303    //              ctiu.copyToImage(diagram, destination, format, new NullProgressMonitor(), PreferencesHint.USE_DEFAULTS);
    304    //      }
    305
    306    }