]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.team.ui/src/org/simantics/team/ui/Common.java
fe48abbbace8ca8eb58471879662e310f31bfdf7
[simantics/platform.git] / bundles / org.simantics.team.ui / src / org / simantics / team / ui / Common.java
1 package org.simantics.team.ui;\r
2 \r
3 import java.lang.reflect.Method;\r
4 import java.util.ArrayList;\r
5 import java.util.Collection;\r
6 import java.util.HashMap;\r
7 import java.util.Iterator;\r
8 import java.util.Map;\r
9 \r
10 import org.eclipse.jface.viewers.ColumnLabelProvider;\r
11 import org.eclipse.jface.viewers.ITreeContentProvider;\r
12 import org.eclipse.jface.viewers.Viewer;\r
13 import org.eclipse.jface.viewers.ViewerCell;\r
14 import org.eclipse.swt.graphics.Image;\r
15 import org.simantics.db.ChangeSet;\r
16 import org.simantics.db.ChangeSetIdentifier;\r
17 import org.simantics.db.Metadata;\r
18 import org.simantics.db.ReadGraph;\r
19 import org.simantics.db.Session;\r
20 import org.simantics.db.common.CommentMetadata;\r
21 import org.simantics.db.common.CommitMetadata;\r
22 import org.simantics.db.common.UndoMetadata;\r
23 import org.simantics.db.common.request.UniqueRead;\r
24 import org.simantics.db.common.utils.Logger;\r
25 import org.simantics.db.exception.DatabaseException;\r
26 import org.simantics.db.service.ManagementSupport;\r
27 import org.simantics.db.service.UndoRedoSupport;\r
28 import org.simantics.team.internal.Images;\r
29 import org.simantics.utils.ui.SWTUtils;\r
30 \r
31 public class Common {\r
32 \r
33 }\r
34 abstract class TreeElement {\r
35     abstract boolean hasChildren();\r
36     abstract Object[] getChildren();\r
37     abstract Image getIdImage();\r
38     abstract String getIdText();\r
39     final Image getDateImage() {\r
40         return null;\r
41     }\r
42     String getDateText() {\r
43         return null;\r
44     }\r
45     final Image getCommentImage() {\r
46         return null;\r
47     }\r
48     String getCommentText() {\r
49         return null;\r
50     }\r
51 }\r
52 class StringElement extends TreeElement {\r
53     protected final String name;\r
54     protected final String value;\r
55     StringElement(String name, String value) {\r
56         this.name = name;\r
57         this.value = value;\r
58     }\r
59     @Override\r
60     protected Image getIdImage() {\r
61         return Images.getInstance().STRING_IMAGE;\r
62     }\r
63     @Override\r
64     protected String getIdText() {\r
65         String s = toString();\r
66         return s.substring(0, Math.min(40, s.length()));\r
67     }\r
68     public String toString() {\r
69         return name + "=" + value;\r
70     }\r
71     @Override\r
72     boolean hasChildren() {\r
73         return false;\r
74     }\r
75     @Override\r
76     Object[] getChildren() {\r
77         return new Object[0];\r
78     }\r
79 }\r
80 class CommentStringElement extends StringElement {\r
81     CommentStringElement(String name, String value) {\r
82         super(name, value);\r
83     }\r
84     @Override\r
85     protected String getIdText() {\r
86         return name.substring(0, Math.min(40, name.length()));\r
87     }\r
88     @Override\r
89     protected String getCommentText() {\r
90         return value;\r
91     }\r
92 }\r
93 class DisplayElement extends TreeElement {\r
94     protected final String name;\r
95     protected final String value;\r
96     DisplayElement(String name, String value) {\r
97         this.name = name;\r
98         this.value = value;\r
99     }\r
100     @Override\r
101     public String toString() {\r
102         return name + "=" + value;\r
103     }\r
104     @Override\r
105     protected Image getIdImage() {\r
106         return Images.getInstance().DISPLAY_IMAGE;\r
107     }\r
108     @Override\r
109     protected String getIdText() {\r
110         return name;\r
111     }\r
112     @Override\r
113     boolean hasChildren() {\r
114         return false;\r
115     }\r
116     @Override\r
117     Object[] getChildren() {\r
118         return new Object[0];\r
119     }\r
120     String getValue() {\r
121         return value;\r
122     }\r
123 }\r
124 class ChangeSetDisplayElement extends DisplayElement {\r
125     private final Session session;\r
126     private final long csid;\r
127     private String lazyValue;\r
128     ChangeSetDisplayElement(String name, Session session, long csid) {\r
129         super(name, "");\r
130         this.session = session;\r
131         this.csid = csid;\r
132     }\r
133     @Override\r
134     public String toString() {\r
135         return name + "=" + getValue();\r
136     }\r
137     @Override\r
138     String getValue() {\r
139         if (null == lazyValue)\r
140             lazyValue = fetchChangeSet();\r
141         return lazyValue;\r
142     }\r
143     private String fetchChangeSet() {\r
144         try {\r
145             Collection<ChangeSet> css = session.sync(new UniqueRead<Collection<ChangeSet>>() {\r
146                 @Override\r
147                 public Collection<ChangeSet> perform(ReadGraph graph) throws DatabaseException {\r
148                     ManagementSupport ms = graph.getService(ManagementSupport.class);\r
149                     return ms.fetchChangeSets(graph, csid, csid);\r
150                 }\r
151             });\r
152             if (css.size() != 1)\r
153                 return "<no change set (1)>";\r
154             return css.iterator().next().toString();\r
155         } catch (DatabaseException e) {\r
156             Logger.defaultLogError(e);\r
157         }\r
158         return "<no change set (2)>";\r
159     }\r
160 }\r
161 class ChangeSetElement extends TreeElement implements Command {\r
162     private boolean DEBUG = false;\r
163     private ChangeSetIdentifier cs;\r
164     private Map<String, byte[]> metadata = null;\r
165     private Session session;\r
166     ChangeSetElement(Session session, long csid) {\r
167         this.session = session;\r
168         this.cs = getChangeSetIdentifier(csid);\r
169     }\r
170     ChangeSetElement(Session session, ChangeSetIdentifier cs) {\r
171         this.cs = cs;\r
172         this.session = session;\r
173     }\r
174     @SuppressWarnings("unchecked")\r
175     static <T> T getMetadata(Session session, Map<String, byte[]> data, Class<? extends Metadata> dataClass) {\r
176         if (null == session || null == data || null == dataClass)\r
177             return null;\r
178         T result = null;\r
179         try {\r
180             Method m = dataClass.getMethod("deserialise", Session.class, byte[].class);\r
181             byte[] bytes = data.get(dataClass.getName());\r
182             if (null != bytes) {\r
183                 Object value = m.invoke(null, session, bytes);\r
184                 result = (T)value;\r
185             }\r
186         } catch (RuntimeException e) {\r
187             Logger.defaultLogError(e);\r
188         } catch (Exception e) {\r
189             Logger.defaultLogError(e);\r
190         }\r
191         return result;\r
192     }\r
193     @Override\r
194     public void dumpToSelectedRevision()\r
195     throws DatabaseException {\r
196         if (null == cs)\r
197             return;\r
198         ManagementSupport ms = session.getService(ManagementSupport.class);\r
199         long csid = cs.getId();\r
200         ms.dumpRevision(csid);\r
201         if (DEBUG)\r
202             System.out.println("DEBUG: Dumped change set=" + csid + ".");\r
203     }\r
204     @Override\r
205     public void undoToSelectedRevision()\r
206     throws DatabaseException {\r
207         if (null == cs)\r
208             return;\r
209         UndoRedoSupport us = session.getService(UndoRedoSupport.class);\r
210         int n = us.undoTo(session, cs.getId());\r
211         if (DEBUG)\r
212             System.out.println("DEBUG: Reverted " + n + " change sets.");\r
213     }\r
214     @Override\r
215     public void initUndoListFromSelectedRevision()\r
216     throws DatabaseException {\r
217         if (null == cs)\r
218             return;\r
219         UndoRedoSupport us = session.getService(UndoRedoSupport.class);\r
220         int n = us.initUndoListFrom(session, cs.getId());\r
221         if (DEBUG)\r
222             System.out.println("DEBUG: Undo list initialised with " + n + " change sets.");\r
223     }\r
224     @Override\r
225     public ChangeSetIdentifier getChangeSetIdentifier() {\r
226         return cs;\r
227     }\r
228     private ChangeSetIdentifier getChangeSetIdentifier(long id) {\r
229         ManagementSupport ms = session.getService(ManagementSupport.class);\r
230         Collection<ChangeSetIdentifier> cids;\r
231         try {\r
232             cids = ms.getChangeSetIdentifiers(id, id);\r
233         } catch (DatabaseException e) {\r
234             Logger.defaultLogError(e);\r
235             return null;\r
236         }\r
237         Iterator<ChangeSetIdentifier> it = cids.iterator();\r
238         while (it.hasNext()) {\r
239             ChangeSetIdentifier cid = it.next();\r
240             if (cid.getId() == id)\r
241                 return cid;\r
242         }\r
243         return null;\r
244     }\r
245     private void getMetadata() {\r
246         if(metadata != null)\r
247             return;\r
248         else if (null == cs) {\r
249             metadata = new HashMap<String, byte[]>();\r
250             return;\r
251         }\r
252         try {\r
253             metadata = cs.getMetadata();\r
254             if (null == metadata) {\r
255                 ChangeSetIdentifier csid = getChangeSetIdentifier(cs.getId());\r
256                 if (null != csid)\r
257                     metadata = csid.getMetadata();\r
258             }\r
259         } catch (Exception e) {\r
260             Logger.defaultLogError(e);\r
261         }\r
262         if (null == metadata)\r
263             metadata = new HashMap<String, byte[]>();\r
264     }\r
265 //    private static final Charset UTF8 = Charset.forName("UTF-8");\r
266 //    private String toString(byte[] data) {\r
267 //        if (data == null)\r
268 //            return "null";\r
269 //        CharsetDecoder decoder = UTF8.newDecoder();\r
270 //        ByteBuffer bbuf = ByteBuffer.wrap(data);\r
271 //        CharBuffer cbuf;\r
272 //        String s = null;\r
273 //        try {\r
274 //            cbuf = decoder.decode(bbuf);\r
275 //            s = cbuf.toString();\r
276 //        } catch (CharacterCodingException e) {\r
277 //            bbuf.rewind();\r
278 //            try {\r
279 //                cbuf = UTF8\r
280 //                .newDecoder()\r
281 //                .onMalformedInput(CodingErrorAction.REPLACE)\r
282 //                .onUnmappableCharacter(CodingErrorAction.REPLACE)\r
283 //                .decode(bbuf);\r
284 //                s = cbuf.toString();\r
285 //            } catch (CharacterCodingException e1) {\r
286 //                return "String conversion error.";\r
287 //            }\r
288 //        }\r
289 //        return s;\r
290 //    }\r
291     @Override\r
292     public String toString() {\r
293         if (null == cs)\r
294             return "<no change set>";\r
295         else\r
296             return "change set " + cs.getId();\r
297     }\r
298     @Override\r
299     boolean hasChildren() {\r
300         if (null == metadata)\r
301             getMetadata();\r
302         if (null == cs && metadata.isEmpty())\r
303             return false;\r
304         else\r
305             return true;\r
306     }\r
307     @Override\r
308     Object[] getChildren() {\r
309         if (null == metadata)\r
310             getMetadata();\r
311         if (null == cs && metadata.isEmpty())\r
312             return new Object[0];\r
313         ArrayList<Object> objects = new ArrayList<Object>();\r
314         if (!metadata.isEmpty()) {\r
315             objects.add(new CommentStringElement("Metaclass", "Count is " + metadata.size() + "."));\r
316     \r
317             CommitMetadata commitMetadata = getMetadata(session, metadata, CommitMetadata.class);\r
318             if (null != commitMetadata) {\r
319                 if (commitMetadata.opid != 0 && commitMetadata.opid != cs.getId())\r
320                     objects.add(new StringElement("Part of operation", "" + commitMetadata.opid));\r
321             }\r
322     \r
323             CommentMetadata commentMetadata = getMetadata(session, metadata, CommentMetadata.class);\r
324             if (null != commentMetadata)\r
325                 objects.add(new DisplayElement("Comment", commentMetadata.toString()));\r
326     \r
327             UndoMetadata undoMetadata = getMetadata(session, metadata, UndoMetadata.class);\r
328             if (null != undoMetadata) {\r
329                 String header = undoMetadata.getHeader();\r
330                 objects.add(new DisplayElement(header, undoMetadata.toString()));\r
331             }\r
332         }\r
333         if (cs.getId() > 0)\r
334             objects.add(new ChangeSetDisplayElement("Change Set", session, cs.getId()));\r
335         \r
336         return objects.toArray();\r
337     }\r
338     Image getIdImage() {\r
339         return Images.getInstance().CHANGE_SET_IMAGE;\r
340     }\r
341     String getIdText() {\r
342         if (null != cs)\r
343             return "" + cs.getId();\r
344         else\r
345             return "<no id>";\r
346     }\r
347     String getDateText() {\r
348         if (null == metadata)\r
349             getMetadata();\r
350         if (null == cs || metadata.isEmpty())\r
351             return "<no date>";\r
352         CommitMetadata commitMetadata = getMetadata(session, metadata, CommitMetadata.class);\r
353         if (null != commitMetadata)\r
354             return commitMetadata.date.toString();\r
355         else\r
356             return "<no date>";\r
357     }\r
358     String getCommentText() {\r
359         if (null == metadata)\r
360             getMetadata();\r
361         if (null == cs || metadata.isEmpty())\r
362             return "<no comment>";\r
363         CommentMetadata commentMetadata = getMetadata(session, metadata, CommentMetadata.class);\r
364         if (null != commentMetadata) {\r
365             UndoMetadata undoMetadata = getMetadata(session, metadata, UndoMetadata.class);\r
366             String t = commentMetadata.toString();\r
367             if (null == undoMetadata)\r
368                 return t;\r
369             else\r
370                 return undoMetadata.getHeader() + ": " + t;\r
371         }\r
372         else\r
373             return "<no comment>";\r
374     }\r
375 }\r
376 abstract class AbstractColumnLabelProvider extends ColumnLabelProvider {\r
377 }\r
378 class IdColumnLabelProvider extends AbstractColumnLabelProvider {\r
379     @Override\r
380     public void update(ViewerCell cell) {\r
381         Object element = cell.getElement();\r
382         if (!(element instanceof TreeElement))\r
383             cell.setText("");\r
384         else {\r
385             TreeElement te = (TreeElement)element;\r
386             String text = te.getIdText();\r
387             if (null != text)\r
388                 cell.setText(text);\r
389             Image image = te.getIdImage();\r
390             if (null!= image)\r
391                 cell.setImage(image);\r
392         }\r
393     }\r
394 }\r
395 class DateColumnLabelProvider extends AbstractColumnLabelProvider {\r
396     @Override\r
397     public void update(ViewerCell cell) {\r
398         Object element = cell.getElement();\r
399         if (!(element instanceof TreeElement))\r
400             cell.setText("");\r
401         else {\r
402             TreeElement te = (TreeElement)element;\r
403             String text = te.getDateText();\r
404             if (null != text)\r
405                 cell.setText(text);\r
406             Image image = te.getDateImage();\r
407             if (null!= image)\r
408                 cell.setImage(image);\r
409         }\r
410     }\r
411 }\r
412 class CommentColumnLabelProvider extends AbstractColumnLabelProvider {\r
413     @Override\r
414     public void update(ViewerCell cell) {\r
415         Object element = cell.getElement();\r
416         if (!(element instanceof TreeElement))\r
417             cell.setText("");\r
418         else {\r
419             TreeElement te = (TreeElement)element;\r
420             String text = te.getCommentText();\r
421             if (null != text)\r
422                 cell.setText(text);\r
423             Image image = te.getCommentImage();\r
424             if (null!= image)\r
425                 cell.setImage(image);\r
426         }\r
427     }\r
428 }\r
429 abstract class ChangeSetProvider implements ITreeContentProvider, ManagementSupport.ChangeSetListener {\r
430     static final boolean DEBUG = false;\r
431     protected final Session session;\r
432     protected final ManagementSupport managementSupport;\r
433     private boolean subscribed = false;\r
434     protected Viewer viewer;\r
435     ChangeSetProvider(Session session) {\r
436         this.session = session;\r
437         this.managementSupport = session.getService(ManagementSupport.class);\r
438         subscribe();\r
439     }\r
440     abstract public Object[] getElements(Object inputElement);\r
441     @Override\r
442     public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
443         this.viewer = viewer;\r
444         subscribe();\r
445     }\r
446     @Override\r
447     public void dispose() {\r
448         managementSupport.cancel(this);\r
449         this.subscribed = false;\r
450     }\r
451     @Override\r
452     public void onChanged(long csid) {\r
453         if (null != viewer && this.subscribed)\r
454             refresh();\r
455     }\r
456     @Override\r
457     public boolean hasChildren(Object element) {\r
458         if (element instanceof  TreeElement)\r
459             return ((TreeElement)element).hasChildren();\r
460         return false;\r
461     }\r
462     @Override\r
463     public Object getParent(Object element) {\r
464         return null;\r
465     }\r
466     @Override\r
467     public Object[] getChildren(Object parentElement) {\r
468         if (parentElement instanceof  TreeElement)\r
469             return ((TreeElement)parentElement).getChildren();\r
470         else\r
471             return null;\r
472     }\r
473     protected void subscribe() {\r
474         if (this.subscribed)\r
475             return;\r
476         managementSupport.subscribe(this);\r
477         this.subscribed = true;\r
478     }\r
479     protected void refresh() {\r
480         if (viewer == null)\r
481             return;\r
482         SWTUtils.asyncExec(viewer.getControl(), new Runnable() {\r
483             @Override\r
484             public void run() {\r
485                 if (!viewer.getControl().isDisposed())\r
486                     viewer.refresh();\r
487             }\r
488         });\r
489     }\r
490 }\r