1
2
3
4
5
6
7
8
9
10
11
12 package sk.uniba.euromath.document;
13 import java.io.IOException;
14 import java.util.Collection;
15 import java.util.EnumSet;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.Map;
19 import java.util.Set;
20 import org.apache.commons.io.FileUtils;
21 import sk.baka.ikslibs.SourceEnum;
22 import sk.baka.xml.gene.CoordinatorInfo;
23 import sk.baka.xml.gene.ExportException;
24 import sk.baka.xml.gene.ICoordinator;
25 import sk.baka.xml.gene.controller.ExportController;
26 import sk.baka.xml.gene.exportgraph.ExportGraph;
27 import sk.baka.xml.gene.exportgraph.ExportGraphBuilder;
28 import sk.baka.xml.gene.exportgraph.GraphNode;
29 import sk.baka.xml.gene.exportgraph.INamespaceAcceptor;
30 import sk.baka.xml.gene.exportgraph.NamespaceMapAcceptor;
31 import sk.baka.xml.gene.exportgraph.TransformGraph;
32 import sk.uniba.euromath.editor.EditorSite;
33 import sk.uniba.euromath.editor.RendererSelector;
34 import sk.uniba.euromath.gene.GeneDataProvider;
35 /***
36 * Represents one presentation of document.
37 * @author Martin Vysny
38 */
39 public final class DocumentView {
40 /***
41 * Graph containing graph nodes for all namespaces present in the document.
42 */
43 private final ExportGraph editGraph;
44 /***
45 * The graph builder.
46 */
47 private final ExportGraphBuilder builder = new ExportGraphBuilder();
48 /***
49 * The data provider instance.
50 */
51 private final GeneDataProvider provider;
52 /***
53 * The document instance.
54 */
55 private final XMLAccess doc;
56 /***
57 * Constructs the instance of object.
58 * @param doc document to view
59 * @param selector selects preferred renderers. May be <code>null</code> -
60 * in such case no renderers are preferred.
61 * @param site the transformed data receiver.
62 */
63 public DocumentView(final XMLAccess doc, final RendererSelector selector,
64 final EditorSite site) {
65 super();
66 this.doc = doc;
67 provider = new GeneDataProvider(
68 selector == null ? new RendererSelector() : selector, doc, site);
69 final INamespaceAcceptor sourceNamespaces = ExportGraphBuilder
70 .getDocumentNamespaces(doc.getSplittedDoc());
71 editGraph = builder.newGraph(sourceNamespaces, provider
72 .getCoordinatorInfo(), true);
73 }
74 /***
75 * The transformation graph, set in {@link #initialize(TransformGraph)}.
76 */
77 private TransformGraph transformGraph = null;
78 /***
79 * Initializes the view, performing the transformation. If an exception is
80 * thrown during export, view is automatically closed and it must not be
81 * further used.
82 * @param graph transform graph.
83 * @throws ExportException if error occurs during the transformation.
84 * @throws IOException if i/o error occurs during the transformation.
85 */
86 public void initialize(final TransformGraph graph) throws ExportException,
87 IOException {
88 checkNotClosed();
89 if (isInitialized())
90 throw new IllegalStateException("View is already initialized.");
91
92 final Set<String> namespaces = new HashSet<String>(editGraph
93 .getAllNodesAsMap().keySet());
94 namespaces.removeAll(graph.allNamespaces());
95 if (!namespaces.isEmpty())
96 throw new ExportException(
97 "Missing transformers for namespaces: " + namespaces);
98 transformGraph = new TransformGraph(graph);
99 boolean initializedProperly = false;
100 try {
101 export();
102 initializedProperly = true;
103 } finally {
104 if (!initializedProperly)
105 close();
106 }
107 }
108 /***
109 * Constructs graph for given set of namespaces.
110 * @param namespaces namespaces
111 * @return graph containing export nodes for all namespaces.
112 */
113 public ExportGraph getGraphFor(
114 final Collection< ? extends String> namespaces) {
115 checkNotClosed();
116
117 final Map<String, GraphNode> allNodes = editGraph.getAllNodesAsMap();
118 final Map<String, EnumSet<SourceEnum>> newNamespaces = new HashMap<String, EnumSet<SourceEnum>>();
119 for (final String ns : namespaces) {
120 if (!allNodes.containsKey(ns))
121 newNamespaces.put(ns, EnumSet.of(SourceEnum.DOM));
122 }
123
124 final CoordinatorInfo info = provider.getCoordinatorInfo();
125 final ExportGraph result = builder.newGraph(new NamespaceMapAcceptor(
126 newNamespaces), info, true);
127
128 for (final String ns : namespaces) {
129 final GraphNode node = allNodes.get(ns);
130 final boolean isRegular = editGraph.isRegular(node);
131 if (node != null)
132 result.addNode(node, isRegular, false);
133 }
134 return result;
135 }
136 /***
137 * Returns the current exporter graph. The graph must not be modified!
138 * @return the exporter graph.
139 */
140 public ExportGraph getEditGraph() {
141 checkNotClosed();
142 return editGraph;
143 }
144 /***
145 * Registers new transformers, ignoring transformers already registered.
146 * @param graph graph to register.
147 */
148 public void addTransformers(final TransformGraph graph) {
149 checkNotClosed();
150 transformGraph.addAll(graph, false);
151 }
152 /***
153 * Exports the document.
154 * @throws ExportException if shit happens.
155 * @throws IOException if i/o error occurs.
156 */
157 void export() throws ExportException, IOException {
158 checkInitialized();
159 checkNotClosed();
160 final ICoordinator editorDataReceiver = provider.getCoordinator();
161 final ExportController controller = new ExportController(FileUtils
162 .toFile(doc.getDocumentURL()), doc.getSplittedDoc(),
163 transformGraph, editorDataReceiver);
164 controller.export(null);
165 }
166 /***
167 * Checks if this view is initialized. Unintialized views are not subjects
168 * for GENE transformation.
169 * @return <code>true</code> if this view is initialized,
170 * <code>false</code> otherwise.
171 */
172 public boolean isInitialized() {
173 return transformGraph != null;
174 }
175 /***
176 * Checks if this view is initialized. If not, exception is thrown.
177 */
178 private void checkInitialized() {
179 if (!isInitialized())
180 throw new IllegalStateException("Not initialized.");
181 }
182 /***
183 * The editor data provider coordinator info.
184 * @return info.
185 */
186 public CoordinatorInfo getCoordinatorInfo() {
187 checkNotClosed();
188 return provider.getCoordinatorInfo();
189 }
190 /***
191 * Closes and invalidates this view. Closing an already closed view has no
192 * effect.
193 */
194 void close() {
195 if (isClosed())
196 return;
197 provider.getCoordinator().dispose();
198 closed = true;
199 }
200 /***
201 * <code>true</code> if this view is closed.
202 */
203 private boolean closed = false;
204 /***
205 * Returns <code>true</code> if this view is closed. If the view is
206 * closed, it becomes invalid and must not be used.
207 * @return <code>true</code> if this view is closed
208 */
209 public boolean isClosed() {
210 return closed;
211 }
212 /***
213 * Checks if this view is closed. If yes then exception is thrown.
214 */
215 private void checkNotClosed() {
216 if (isClosed())
217 throw new IllegalStateException("The view is closed.");
218 }
219
220
221
222
223 @Override
224 protected void finalize() throws Throwable {
225 close();
226 super.finalize();
227 }
228 }