    001    package com.hammurapi.render.emf;
    002
    003    import java.io.File;
    004    import java.util.ArrayList;
    005    import java.util.HashMap;
    006    import java.util.IdentityHashMap;
    007    import java.util.List;
    008    import java.util.Locale;
    009    import java.util.Map;
    010
    011    import org.apache.tools.ant.BuildException;
    012    import org.apache.tools.ant.Task;
    013    import org.eclipse.emf.common.util.TreeIterator;
    014    import org.eclipse.emf.common.util.URI;
    015    import org.eclipse.emf.ecore.EClassifier;
    016    import org.eclipse.emf.ecore.EObject;
    017    import org.eclipse.emf.ecore.EPackage;
    018    import org.eclipse.emf.ecore.resource.Resource;
    019    import org.eclipse.emf.ecore.resource.ResourceSet;
    020    import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
    021    import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
    022    import org.eclipse.gmf.runtime.notation.Diagram;
    023    import org.eclipse.gmf.runtime.notation.NotationPackage;
    024
    025    import com.hammurapi.common.Context;
    026    import com.hammurapi.common.DefaultContext;
    027    import com.hammurapi.common.IdentityManager;
    028    import com.hammurapi.render.RenderingConstants;
    029    import com.hammurapi.render.RenderingException;
    030    import com.hammurapi.render.ReportGenerator;
    031
    032    /**
    033     * Generates HTML documentation for ECore models and diagrams.
    034     * @author Pavel Vlasov
    035     *
    036     */
    037    public class EcoreDoc extends Task {
    038
    039            @Override
    040            public void execute() throws BuildException {
    041                    long start = System.currentTimeMillis();
    042
    043                    if (outputDir==null && outputFile==null) {
    044                            throw new BuildException("Either outputdir or outputfile must be set.");
    045                    }
    046
    047                    if (outputDir!=null && !outputDir.exists()) {
    048                            outputDir.mkdirs();
    049                    }
    050
    051                    ResourceSet resourceSet = new ResourceSetImpl();
    052
    053                    resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(
    054                                    Resource.Factory.Registry.DEFAULT_EXTENSION,
    055                                    new XMIResourceFactoryImpl());
    056
    057                    resourceSet.getPackageRegistry().put(NotationPackage.eNS_URI, NotationPackage.eINSTANCE);
    058
    059                    File file = getProject()==null ? new File(diagram) : new File(getProject().getBaseDir(), diagram);
    060                    URI uri = file.isFile() ? URI.createFileURI(file.getAbsolutePath()): URI.createURI(diagram);
    061
    062                    Resource resource = resourceSet.getResource(uri, true);
    063
    064                    Model model = new Model();
    065
    066                    ReportGenerator generator = new ReportGenerator();
    067
    068                    Map<String, Object> env = new HashMap<String, Object>();
    069                    env.put(RenderingConstants.RENDER_START, start);
    070                    Context context = new DefaultContext(EcoreDoc.class.getClassLoader(), null);
    071                    IdentityManager<?> identityManager = context.lookup(IdentityManager.class);
    072                    env.put(RenderingConstants.RENDER_HELPER, new ModelRenderHelper(identityManager, outputDir==null ? outputFile.getParentFile() : outputDir, diagramMap, model, env, context, locale, http));
    073
    074                    generator.setEnvironment(env);
    075                    generator.setContext(context);
    076
    077                    for (EObject obj: resource.getContents()) {
    078                            mapDiagram(obj);
    079                            TreeIterator<EObject> it = obj.eAllContents();
    080                            while (it.hasNext()) {
    081                                    EObject next = it.next();
    082                                    mapDiagram(next);
    083                            }
    084                    }
    085
    086
    087                    for (EObject obj: resource.getContents()) {
    088                            if (obj instanceof Diagram) {
    089                                    Diagram diagram = (Diagram) obj;
    090
    091                                    EObject diagramElement = diagram.getElement();
    092
    093                                    if (diagramElement instanceof EPackage) {
    094                                            EPackage pkg = (EPackage) diagramElement;
    095                                            while (pkg.getESuperPackage()!=null) {
    096                                                    pkg = pkg.getESuperPackage();
    097                                            }
    098                                            if (!model.getRootPackages().contains(pkg)) {
    099                                                    model.getRootPackages().add(pkg);
    100                                            }
    101                                    } else if (diagramElement instanceof EClassifier) {
    102                                            EPackage pkg = ((EClassifier) diagramElement).getEPackage();
    103                                            while (pkg.getESuperPackage()!=null) {
    104                                                    pkg = pkg.getESuperPackage();
    105                                            }
    106                                            if (!model.getRootPackages().contains(pkg)) {
    107                                                    model.getRootPackages().add(pkg);
    108                                            }
    109                                    }
    110                                    model.getDiagrams().add(diagram);
    111                            } else {
    112                                    System.err.println("Unexpected contents: "+obj);
    113                            }
    114                    }
    115
    116                    try {
    117                            if (outputDir==null) {
    118                                    generator.generate(model, outputFile, "Model documentation", "onepage", http);
    119                            } else {
    120                                    generator.generate(model, outputDir, "Model documentation", http);
    121                            }
    122                    } catch (RenderingException e) {
    123                            throw new BuildException(e);
    124                    }
    125            }
    126
    127            private String diagram;
    128            private File outputDir;
    129            private File outputFile;
    130            private Locale locale;
    131            private boolean http;
    132
    133            /**
    134             * Sets rendering locale.
    135             * @param locale
    136             */
    137            public void setLocale(Locale locale) {
    138                    this.locale = locale;
    139            }
    140
    141            /**
    142             * Source diagram - file or URL
    143             * @return
    144             */
    145            public String getDiagram() {
    146                    return diagram;
    147            }
    148
    149            /**
    150             * Source diagram - file or URL
    151             * @param diagram
    152             */
    153            public void setDiagram(String diagram) {
    154                    this.diagram = diagram;
    155            }
    156
    157            /**
    158             * Output directory
    159             * @return
    160             */
    161            public File getOutputDir() {
    162                    return outputDir;
    163            }
    164
    165            /**
    166             * Output directory
    167             * @param outputDir
    168             */
    169            public void setOutputDir(File outputDir) {
    170                    if (outputFile!=null) {
    171                            throw new BuildException("outputdir and outputfile are mutually exclusive");
    172                    }
    173                    this.outputDir = outputDir;
    174            }
    175
    176            public File getOutputFile() {
    177                    return outputFile;
    178            }
    179
    180            /**
    181             * If outputfile attribute is set, then the task generates documenation in a single HTML file. Convenient for printing.
    182             * @param outputFile
    183             */
    184            public void setOutputFile(File outputFile) {
    185                    if (outputDir!=null) {
    186                            throw new BuildException("outputdir and outputfile are mutually exclusive");
    187                    }
    188                    this.outputFile = outputFile;
    189            }
    190
    191            public boolean isHttp() {
    192                    return http;
    193            }
    194
    195            /**
    196             * If true, outline and contents trees are rendered to use AJAX. It is useful for
    197             * large models, but works only over HTTP.
    198             * @param http
    199             */
    200            public void setHttp(boolean http) {
    201                    this.http = http;
    202            }
    203
    204            // Assigns ID's to elements for rendering.
    205            private static Map<EObject, List<Diagram>> diagramMap = new IdentityHashMap<EObject, List<Diagram>>();
    206
    207            /**
    208             * Generates documentation from a diagram file.
    209             * Command line parameters: &lt;diagram file&gt; &lt;output dir&gt; [http]
    210             * @param args
    211             */
    212            public static void main(String[] args) throws Exception {
    213                    System.out.println("Command line parameters: <diagram file> <output dir> [http]");
    214                    System.out.println("Example: mymodel.ecorediag model-doc");
    215
    216                    EcoreDoc documenter = new EcoreDoc();
    217                    documenter.setDiagram(args[0]);
    218                    documenter.setOutputDir(new File(args[1]));
    219                    documenter.setHttp(args.length>2 ? "http".equals(args[2]) : false);
    220                    documenter.execute();
    221            }
    222
    223            private static void mapDiagram(EObject next) {
    224                    if (next instanceof Diagram) {
    225                            Diagram diagram = (Diagram) next;
    226                            EObject diagramElement = diagram.getElement();
    227                            if (diagramElement!=null) {
    228                                    List<Diagram> diagrams = diagramMap.get(diagramElement);
    229                                    if (diagrams == null) {
    230                                            diagrams = new ArrayList<Diagram>();
    231                                            diagramMap.put(diagramElement, diagrams);
    232                                    }
    233                                    diagrams.add(diagram);
    234                            }
    235                    }
    236            }
    237
    238    }