/******************************************************************************* * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Exadel, Inc. and Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.common.meta.impl.documentation; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import org.jboss.tools.common.model.XModel; import org.jboss.tools.common.model.XModelObject; import org.jboss.tools.common.model.XModelObjectConstants; import org.jboss.tools.common.model.plugin.ModelPlugin; import org.jboss.tools.common.model.util.XMLUtil; import org.jboss.tools.common.model.util.XModelObjectLoaderUtil; import org.w3c.dom.Element; public class DocumentGenerator { private XModelObject meta = null; private String filename = null; private Parents parents = null; public DocumentGenerator() {} public void setModel(XModel model) { meta = model.getRoot().getChildByPath("MetaModel"); //$NON-NLS-1$ } public void generate(String filename) { if(meta == null) throw new IllegalStateException("Meta root is not set."); //$NON-NLS-1$ this.filename = filename; Element g = XMLUtil.createDocumentElement("html"); //$NON-NLS-1$ generateTitle(g); generateHead(g); generateBody(g); try { XModelObjectLoaderUtil.serialize(g, filename); replace(); } catch (IOException e) { ModelPlugin.getPluginLog().logError(e); } } protected void generateTitle(Element e) { Element t = XMLUtil.createElement(e, "title"); //$NON-NLS-1$ XMLUtil2.createText(t, "Entity list"); } protected void generateHead(Element e) { Element h = XMLUtil.createElement(e, "head"); //$NON-NLS-1$ Element s = XMLUtil.createElement(h, "style"); //$NON-NLS-1$ XMLUtil2.createText(s, new StyleGenerator().getStyle()); } protected void generateBody(Element e) { Element b = XMLUtil.createElement(e, XModelObjectConstants.ATTR_NAME_BODY); XModelObject entities = meta.getChildren("MetaEntities")[0]; //$NON-NLS-1$ parents = new Parents(); parents.set(entities); parents.compile(); new ContentGenerator().generate(b, entities); processGroup(b, entities); } protected void processGroup(Element e, XModelObject o) { XModelObject[] es = o.getChildren("MetaEntity"); //$NON-NLS-1$ for (int i = 0; i < es.length; i++) processEntity(e, es[i]); XModelObject[] gs = o.getChildren("MetaEntityGroup"); //$NON-NLS-1$ for (int i = 0; i < gs.length; i++) processGroup(e, gs[i]); } protected void processEntity(Element e, XModelObject o) { XMLUtil2.hr(e); Element t = XMLUtil.createElement(e, "table"); //$NON-NLS-1$ XMLUtil2.entityRow(t, "Name:", o.getAttributeValue(XModelObjectConstants.ATTR_NAME)); XMLUtil2.simpleRow(t, "Editor:", o.getAttributeValue("editor")); //$NON-NLS-2$ processHierarchy(e, o); processAttributeList(e, o.getChildren("MetaAttributes")[0]); //$NON-NLS-1$ processActionList(e, o.getChildren("MetaActionList")[0]); //$NON-NLS-1$ } protected void processHierarchy(Element e, XModelObject o) { Element t = XMLUtil.createElement(e, "table"); //$NON-NLS-1$ t.setAttribute("width", "600"); //$NON-NLS-1$ //$NON-NLS-2$ Element tr = XMLUtil.createElement(t, "tr"); //$NON-NLS-1$ for (int i = 0; i < 2; i++) { Element td = XMLUtil.createElement(tr, "td"); //$NON-NLS-1$ td.setAttribute("width", "300"); //$NON-NLS-1$ //$NON-NLS-2$ } tr = XMLUtil.createElement(t, "tr"); //$NON-NLS-1$ Element td = XMLUtil.createElement(tr, "td"); //$NON-NLS-1$ td.setAttribute("valign", "top"); //$NON-NLS-1$ //$NON-NLS-2$ processParents(td, o); td = XMLUtil.createElement(tr, "td"); //$NON-NLS-1$ td.setAttribute("valign", "top"); //$NON-NLS-1$ //$NON-NLS-2$ processChildren(td, o.getChildren("MetaChildren")[0]); //$NON-NLS-1$ } protected void processParents(Element e, XModelObject o) { Element lt = XMLUtil2.createSubTitle(e, "Can be inside:"); ArrayList<String> v = parents.get(o); if(v.size() == 0) { XMLUtil2.createText(lt, "None"); XMLUtil.createElement(lt, "br"); //$NON-NLS-1$ } else for (int i = 0; i < v.size(); i++) { Element s = XMLUtil.createElement(lt, "span"); //$NON-NLS-1$ s.setAttribute("class", "value"); //$NON-NLS-1$ //$NON-NLS-2$ XMLUtil2.createEntityReference(s, v.get(i)); XMLUtil.createElement(lt, "br"); //$NON-NLS-1$ } } protected void processChildren(Element e, XModelObject o) { Element lt = XMLUtil2.createSubTitle(e, "Possible children:"); XModelObject[] as = o.getChildren(); if(as.length == 0) { XMLUtil2.createText(lt, "None"); return; } Element t = createTable(lt); Element tr = XMLUtil.createElement(t, "tr"); //$NON-NLS-1$ createHeaderCell(tr, "Name", 0); createHeaderCell(tr, "Required", 0); for (int i = 0; i < as.length; i++) { tr = XMLUtil.createElement(tr, "tr"); //$NON-NLS-1$ Element td = XMLUtil.createElement(tr, "td"); //$NON-NLS-1$ td.setAttribute("class", "value"); //$NON-NLS-1$ //$NON-NLS-2$ XMLUtil2.createEntityReference(td, as[i].getAttributeValue(XModelObjectConstants.ATTR_NAME)); createValueCell(tr, as[i].getAttributeValue("required")); //$NON-NLS-1$ } } protected void processAttributeList(Element e, XModelObject o) { Element lt = XMLUtil2.createSubTitle(e, "Attribute List:"); Element t = createTable(lt); Element tr = XMLUtil.createElement(t, "tr"); //$NON-NLS-1$ createHeaderCell(tr, "Name", 130); createHeaderCell(tr, "Visible", 50); createHeaderCell(tr, "Editor", 0); createHeaderCell(tr, "Default Value", 0); createHeaderCell(tr, "Possible Values", 0); XModelObject[] as = o.getChildren("MetaAttribute"); //$NON-NLS-1$ for (int i = 0; i < as.length; i++) { tr = XMLUtil.createElement(tr, "tr"); //$NON-NLS-1$ createValueCell(tr, as[i].getAttributeValue(XModelObjectConstants.ATTR_NAME)); createValueCell(tr, as[i].getAttributeValue("visibility")); //$NON-NLS-1$ XModelObject oe = as[i].getChildren("MetaAttributeEditor")[0]; //$NON-NLS-1$ String ed = oe.getAttributeValue(XModelObjectConstants.ATTR_NAME); createValueCell(tr, ed); String dv = as[i].getAttributeValue("default value"); //$NON-NLS-1$ createValueCell(tr, dv); XModelObject oc = as[i].getChildren("MetaAttributeConstraint")[0]; //$NON-NLS-1$ String cl = oc.getAttributeValue("loader"); //$NON-NLS-1$ if(cl.startsWith("List")) { //$NON-NLS-1$ processListConstraint(tr, oc); } else if(cl.length() == 0 && "Uneditable".equals(ed)) { //$NON-NLS-1$ createValueCell(tr, dv); } else if(cl.length() == 0 && "Int".equals(ed)) { //$NON-NLS-1$ createValueCell(tr, "integer"); //$NON-NLS-1$ } else { createValueCell(tr, "any"); //$NON-NLS-1$ } } } Element createTable(Element e) { Element t = XMLUtil.createElement(e, "table"); //$NON-NLS-1$ t.setAttribute("border", "1"); //$NON-NLS-1$ //$NON-NLS-2$ t.setAttribute("cellspacing", "0"); //$NON-NLS-1$ //$NON-NLS-2$ t.setAttribute("cellpadding", "2"); //$NON-NLS-1$ //$NON-NLS-2$ return t; } void createHeaderCell(Element e, String name, int width) { Element td = XMLUtil.createElement(e, "td"); //$NON-NLS-1$ td.setAttribute("class", XModelObjectConstants.ATTR_NAME); //$NON-NLS-1$ if(width > 0) td.setAttribute("width", "" + width); //$NON-NLS-1$ //$NON-NLS-2$ XMLUtil2.createText(td, name); } void createValueCell(Element e, String value) { Element td = XMLUtil.createElement(e, "td"); //$NON-NLS-1$ if(value.length() == 0) value = " "; //$NON-NLS-1$ td.setAttribute("class", "value"); //$NON-NLS-1$ //$NON-NLS-2$ XMLUtil2.createText(td, value); } void processListConstraint(Element e, XModelObject o) { Element td = XMLUtil.createElement(e, "td"); //$NON-NLS-1$ XModelObject[] vs = o.getChildren(); for (int i = 0; i < vs.length; i++) { Element s = XMLUtil.createElement(td, "span"); //$NON-NLS-1$ s.setAttribute("class", "value"); //$NON-NLS-1$ //$NON-NLS-2$ XMLUtil2.createText(s, vs[i].getAttributeValue(XModelObjectConstants.ATTR_NAME)); XMLUtil.createElement(td, "br"); //$NON-NLS-1$ } } protected void processActionList(Element e, XModelObject o) { Element lt = XMLUtil2.createSubTitle(e, "Action List:"); int i = o.getChildren().length; if(i > 0) { Element ul = XMLUtil.createElement(lt, "ul"); //$NON-NLS-1$ processAction(ul, o); } else { XMLUtil2.createText(lt, "Empty"); } } protected void processAction(Element e, XModelObject o) { XModelObject[] os = o.getChildren(); for (int i = 0; i < os.length; i++) { if("MetaActionList".equals(os[i].getModelEntity().getName())) { //$NON-NLS-1$ if("0".equals(os[i].getAttributeValue("group"))) { //$NON-NLS-1$ //$NON-NLS-2$ processAction(e, os[i]); XMLUtil2.hr(e, 100); } else { Element li = XMLUtil.createElement(e, "li"); //$NON-NLS-1$ XMLUtil2.createText(li, os[i].getAttributeValue("display name")); //$NON-NLS-1$ Element ul = XMLUtil.createElement(e, "ul"); //$NON-NLS-1$ processAction(ul, os[i]); } } else { Element li = XMLUtil.createElement(e, "li"); //$NON-NLS-1$ XMLUtil2.createText(li, os[i].getAttributeValue("display name")); //$NON-NLS-1$ } } } class Parents { private Hashtable<String,XModelObject> ent = new Hashtable<String,XModelObject>(); private Hashtable<String,ArrayList<String>> par = new Hashtable<String,ArrayList<String>>(); public void set(XModelObject o) { XModelObject[] cs = o.getChildren("MetaEntityGroup"); //$NON-NLS-1$ for (int i = 0; i < cs.length; i++) set(cs[i]); cs = o.getChildren("MetaEntity"); //$NON-NLS-1$ for (int i = 0; i < cs.length; i++) { String n = cs[i].getAttributeValue(XModelObjectConstants.ATTR_NAME); ent.put(n, cs[i]); par.put(n, new ArrayList<String>()); } } public void compile() { Iterator it = ent.values().iterator(); while(it.hasNext()) { XModelObject o = (XModelObject)it.next(); String p = o.getAttributeValue(XModelObjectConstants.ATTR_NAME); XModelObject[] os = o.getChildren("MetaChildren")[0].getChildren(); //$NON-NLS-1$ for (int i = 0; i < os.length; i++) { String n = os[i].getAttributeValue(XModelObjectConstants.ATTR_NAME); ArrayList<String> v = par.get(n); if(v != null) v.add(p); } } } public ArrayList<String> get(XModelObject o) { return par.get(o.getAttributeValue(XModelObjectConstants.ATTR_NAME)); } } protected void replace() { StringBuffer sb = new StringBuffer(); BufferedReader br = null; try { br = new BufferedReader(new FileReader(new File(filename))); char[] b = new char[256]; int i = 0; while((i = br.read(b, 0, 256)) > 0) { sb.append(b, 0, i); } } catch (IOException e) { ModelPlugin.getPluginLog().logError(e); } finally { try { if(br!=null) { br.close(); } } catch (IOException e) { // ignore } } int i = 0; while(i < sb.length()) { if(sb.charAt(i) == '&') sb.replace(i + 1, i + 5, ""); //$NON-NLS-1$ i++; } try { PrintWriter bw = new PrintWriter(new FileWriter(new File(filename))); bw.print(sb.toString()); bw.flush(); bw.close(); } catch (IOException e) { ModelPlugin.getPluginLog().logError(e); } } } class StyleGenerator { public String getStyle() { return ".name{ font-size: 12pt; text-align: right; vertical-align:top }\n" + //$NON-NLS-1$ ".value{ font-size: 12pt; font-weight: bold; vertical-align:top }\n" + //$NON-NLS-1$ ".title{ font-size: 14pt; }\n" + //$NON-NLS-1$ ".listtab{ font-size: 12pt; margin-left: 20px; vertical-align:top }\n" + //$NON-NLS-1$ "UL{ list-style: none; margin-left: 20px; }\n"; //$NON-NLS-1$ } } class XMLUtil2 { public static void createText(Element e, String text) { e.appendChild(e.getOwnerDocument().createTextNode(text)); } public static void hr(Element e) { XMLUtil.createElement(e, "hr"); //$NON-NLS-1$ } public static void hr(Element e, int length) { Element h = XMLUtil.createElement(e, "hr"); //$NON-NLS-1$ h.setAttribute("width", "" + length); //$NON-NLS-1$ //$NON-NLS-2$ h.setAttribute("align", "left"); //$NON-NLS-1$ //$NON-NLS-2$ } public static void simpleRow(Element e, String name, String value) { Element tr = XMLUtil.createElement(e, "tr"); //$NON-NLS-1$ Element td1 = XMLUtil.createElement(tr, "td"); //$NON-NLS-1$ td1.setAttribute("class", XModelObjectConstants.ATTR_NAME); //$NON-NLS-1$ createText(td1, name); Element td2 = XMLUtil.createElement(tr, "td"); //$NON-NLS-1$ td1.setAttribute("class", "value"); //$NON-NLS-1$ //$NON-NLS-2$ createText(td2, value); } public static Element createSubTitle(Element e, String title) { Element p = XMLUtil.createElement(e, "p"); //$NON-NLS-1$ p.setAttribute("class", "title"); //$NON-NLS-1$ //$NON-NLS-2$ XMLUtil2.createText(p, title); Element lt = XMLUtil.createElement(e, "p"); //$NON-NLS-1$ lt.setAttribute("class", "listtab"); //$NON-NLS-1$ //$NON-NLS-2$ return lt; } public static void entityRow(Element e, String name, String value) { Element tr = XMLUtil.createElement(e, "tr"); //$NON-NLS-1$ Element td1 = XMLUtil.createElement(tr, "td"); //$NON-NLS-1$ td1.setAttribute("class", XModelObjectConstants.ATTR_NAME); //$NON-NLS-1$ createText(td1, name); Element td2 = XMLUtil.createElement(tr, "td"); //$NON-NLS-1$ td1.setAttribute("class", "value"); //$NON-NLS-1$ //$NON-NLS-2$ Element a = XMLUtil.createElement(td2, "a"); //$NON-NLS-1$ a.setAttribute(XModelObjectConstants.ATTR_NAME, value); createText(a, value); } public static void createEntityReference(Element e, String value) { Element a = XMLUtil.createElement(e, "a"); //$NON-NLS-1$ a.setAttribute("href", "#" + value); //$NON-NLS-1$ //$NON-NLS-2$ createText(a, value); } } class ContentGenerator { private HashMap<String,XModelObject> list = new HashMap<String,XModelObject>(); public void generate(Element element, XModelObject o) { processGroup(o); XMLUtil2.createSubTitle(element, "Entities"); String[] keys = (String[])list.keySet().toArray(new String[0]); Arrays.sort(keys); char c = ' '; for (int i = 0; i < keys.length; i++) { char cx = keys[i].charAt(0); if(cx != c) { c = cx; XMLUtil2.createSubTitle(element, "" + c); //$NON-NLS-1$ } XMLUtil2.createEntityReference(element, keys[i]); } } private void processGroup(XModelObject o) { XModelObject[] es = o.getChildren("MetaEntity"); //$NON-NLS-1$ for (int i = 0; i < es.length; i++) list.put(es[i].getAttributeValue(XModelObjectConstants.ATTR_NAME), es[i]); XModelObject[] gs = o.getChildren("MetaEntityGroup"); //$NON-NLS-1$ for (int i = 0; i < gs.length; i++) processGroup(gs[i]); } }