--- /dev/null
+package org.simantics.document.linking.report.templates;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.Comparator;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.document.DocumentResource;\r
+import org.simantics.document.linking.report.Document;\r
+import org.simantics.document.linking.report.DocumentTitlePage;\r
+import org.simantics.document.linking.report.RowContentProvider;\r
+import org.simantics.document.linking.report.Table;\r
+import org.simantics.document.linking.report.TextItem;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+\r
+\r
+\r
+/**\r
+ * Writes report with Model's internal documents.\r
+ * \r
+ * Model information\r
+ □ Document folder 1\r
+ • Document 1-1\r
+ • Document 1-2 rev1\r
+ • Document 1-2 rev2\r
+ • Document 1-2 rev3\r
+ • Document 1-3\r
+ □ Document folder 2\r
+ • Document folder 3\r
+ o Document 3-1\r
+ o Document 3-2\r
+ • Document folder 4\r
+ o Document 4-1\r
+ o Document 4-2\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class ModelDocumentWriter extends DocumentWriter<List<Resource>> {\r
+ \r
+ ReadGraph graph;\r
+ Layer0 l0;\r
+ Resource model;\r
+ Map<Object, Object> context;\r
+ Comparator<Resource> comparator;\r
+\r
+ \r
+ @Override\r
+ public String getName() {\r
+ return "Model Internal Documents";\r
+ }\r
+ \r
+ @Override\r
+ public void start(ReadGraph graph, Resource model, Document lineWriter, Map<Object, Object> context) throws Exception{\r
+ super.start(graph, model, lineWriter, context);\r
+ this.context = context;\r
+ this.model = model;\r
+ DocumentTitlePage titlePage = lineWriter.newElement(DocumentTitlePage.class);\r
+ titlePage.writeTitle(graph, context);\r
+ Table table = lineWriter.newElement(Table.class);\r
+ table.addColumn("Folder", 0.4);\r
+ table.addColumn("Document", 0.6);\r
+ \r
+ //lineWriter.nextPage();\r
+ this.graph = graph;\r
+ this.l0 = Layer0.getInstance(graph);\r
+ clearProviders();\r
+ addCellProvider(new HierarchyContentProvider());\r
+ addCellProvider(new DocumentContentProvider());\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public List<List<Resource>> getReportItems(ReadGraph graph) throws DatabaseException {\r
+ \r
+ comparator = new ResourceNameComparator(graph, model);\r
+ List<List<Resource>> result = new ArrayList<List<Resource>>();\r
+ List<Resource> root = Collections.singletonList(model);\r
+ collect(graph, root, result);\r
+ return result;\r
+ }\r
+ \r
+ private void collect(ReadGraph graph, List<Resource> location, List<List<Resource>> result) throws DatabaseException{\r
+ // TODO : at the moment document structure in the model is customizable, so this method may not be able to collect the documents.\r
+ // Current logic is:\r
+ // 1. browse L0.ConsistsOf\r
+ // 2a. If found resource is Document, add it into results\r
+ // 2b. Otherwise, if resource is not structural component, go to step 1. \r
+ // \r
+ // Note: Filtering structural components prevents browsing the whole model structure for locating the documents.\r
+ \r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ DocumentResource doc = DocumentResource.getInstance(graph);\r
+ StructuralResource2 sr = StructuralResource2.getInstance(graph);\r
+ Resource lastInPath = location.get(location.size() -1);\r
+ List<Resource> set = new ArrayList<Resource>();\r
+ set.addAll(graph.getObjects(lastInPath, l0.ConsistsOf));\r
+ Collections.sort(set, comparator);\r
+ for (Resource r : set) {\r
+ List<Resource> path = new ArrayList<Resource>(location.size()+1);\r
+ path.addAll(location);\r
+ path.add(r);\r
+ if (graph.isInstanceOf(r, doc.Document)) {\r
+ result.add(path);\r
+ collect(graph, path, result);\r
+ } else if (!graph.isInstanceOf(r, sr.Component)){\r
+ collect(graph, path, result);\r
+ }\r
+ }\r
+ }\r
+ \r
+ \r
+ \r
+ \r
+ private String getText(List<Resource> current, boolean indent) throws DatabaseException {\r
+ String text = "";\r
+ if (indent)\r
+ for (int i = 0; i < current.size()-1; i++) {\r
+ text += " ";\r
+ }\r
+ \r
+ text += NameUtils.getSafeLabel(graph, current.get(current.size()-1));\r
+ return text;\r
+ }\r
+ \r
+ private class HierarchyContentProvider implements RowContentProvider<List<Resource>> {\r
+ @Override\r
+ public void setText(Document writer, List<Resource> previous,\r
+ List<Resource> current, List<Resource> next, TextItem[] text)\r
+ throws Exception {\r
+ int writeFolder = 0;\r
+ int fic = folderIndex(current);\r
+ if (previous == null) {\r
+ writeFolder = fic+1;\r
+ } else {\r
+ int fip = folderIndex(previous);\r
+ \r
+ if (fip < fic) {\r
+ writeFolder = fic-fip;\r
+ } else if (fip == fic) {\r
+ for (int i = 0; i <= fic; i++) {\r
+ if (!previous.get(i).equals(current.get(i))) {\r
+ writeFolder = previous.size()-i;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ if (writeFolder > 0) {\r
+ text[0] = writer.newItem(TextItem.class);\r
+ if (writeFolder > 1) {\r
+ Table table = writer.getCurrentElement(Table.class);\r
+ for (int i = current.size()-writeFolder+1; i < current.size()-1; i++) {\r
+ text[0].setText(getText(current.subList(0, i),true));\r
+ text[1] = null;\r
+ table.writeRowItem(text);\r
+ }\r
+ }\r
+ text[0].setText(getText(current.subList(0, fic+1),true));\r
+ } else {\r
+ text[0] = null;\r
+ }\r
+ \r
+ }\r
+ }\r
+ \r
+ private int folderIndex(List<Resource> path) throws DatabaseException{\r
+ for (int i = path.size()-1; i >= 0; i--) {\r
+ if (graph.isInstanceOf(path.get(i), doc.Document))\r
+ continue;\r
+ return i;\r
+ }\r
+ return -1;\r
+ }\r
+ \r
+ private int revisionIndex(Resource document) throws DatabaseException{\r
+ Resource r = document;\r
+ int i = -1;\r
+ while (r != null) {\r
+ Resource r2 = graph.getPossibleObject(r, l0.PartOf);\r
+ r = graph.getPossibleObject(r, doc.HasNewerVersion);\r
+ i++;\r
+ if (r2 != null && !r2.equals(r)) // prevent indent if document revisions are not in tree form.\r
+ break;\r
+ }\r
+ return i;\r
+ }\r
+ \r
+ private class DocumentContentProvider implements RowContentProvider<List<Resource>> {\r
+ public void setText(Document writer, java.util.List<Resource> previous, java.util.List<Resource> current, java.util.List<Resource> next, TextItem[] row) throws Exception {\r
+ String s = "";\r
+ \r
+ Resource document = current.get(current.size()-1);\r
+ int rev = revisionIndex(document);\r
+ for (int i = 0; i < rev; i++)\r
+ s += " ";\r
+ row[1] = getDocumentItem(document);\r
+ row[1].setText(s + row[1].getText());\r
+ };\r
+ }\r
+\r
+}\r