1 package org.simantics.team.ui;
\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
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
31 public class Common {
\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
42 String getDateText() {
\r
45 final Image getCommentImage() {
\r
48 String getCommentText() {
\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
60 protected Image getIdImage() {
\r
61 return Images.getInstance().STRING_IMAGE;
\r
64 protected String getIdText() {
\r
65 String s = toString();
\r
66 return s.substring(0, Math.min(40, s.length()));
\r
68 public String toString() {
\r
69 return name + "=" + value;
\r
72 boolean hasChildren() {
\r
76 Object[] getChildren() {
\r
77 return new Object[0];
\r
80 class CommentStringElement extends StringElement {
\r
81 CommentStringElement(String name, String value) {
\r
85 protected String getIdText() {
\r
86 return name.substring(0, Math.min(40, name.length()));
\r
89 protected String getCommentText() {
\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
101 public String toString() {
\r
102 return name + "=" + value;
\r
105 protected Image getIdImage() {
\r
106 return Images.getInstance().DISPLAY_IMAGE;
\r
109 protected String getIdText() {
\r
113 boolean hasChildren() {
\r
117 Object[] getChildren() {
\r
118 return new Object[0];
\r
120 String getValue() {
\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
130 this.session = session;
\r
134 public String toString() {
\r
135 return name + "=" + getValue();
\r
138 String getValue() {
\r
139 if (null == lazyValue)
\r
140 lazyValue = fetchChangeSet();
\r
143 private String fetchChangeSet() {
\r
145 Collection<ChangeSet> css = session.sync(new UniqueRead<Collection<ChangeSet>>() {
\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
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
158 return "<no change set (2)>";
\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
170 ChangeSetElement(Session session, ChangeSetIdentifier cs) {
\r
172 this.session = session;
\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
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
186 } catch (RuntimeException e) {
\r
187 Logger.defaultLogError(e);
\r
188 } catch (Exception e) {
\r
189 Logger.defaultLogError(e);
\r
194 public void dumpToSelectedRevision()
\r
195 throws DatabaseException {
\r
198 ManagementSupport ms = session.getService(ManagementSupport.class);
\r
199 long csid = cs.getId();
\r
200 ms.dumpRevision(csid);
\r
202 System.out.println("DEBUG: Dumped change set=" + csid + ".");
\r
205 public void undoToSelectedRevision()
\r
206 throws DatabaseException {
\r
209 UndoRedoSupport us = session.getService(UndoRedoSupport.class);
\r
210 int n = us.undoTo(session, cs.getId());
\r
212 System.out.println("DEBUG: Reverted " + n + " change sets.");
\r
215 public void initUndoListFromSelectedRevision()
\r
216 throws DatabaseException {
\r
219 UndoRedoSupport us = session.getService(UndoRedoSupport.class);
\r
220 int n = us.initUndoListFrom(session, cs.getId());
\r
222 System.out.println("DEBUG: Undo list initialised with " + n + " change sets.");
\r
225 public ChangeSetIdentifier getChangeSetIdentifier() {
\r
228 private ChangeSetIdentifier getChangeSetIdentifier(long id) {
\r
229 ManagementSupport ms = session.getService(ManagementSupport.class);
\r
230 Collection<ChangeSetIdentifier> cids;
\r
232 cids = ms.getChangeSetIdentifiers(id, id);
\r
233 } catch (DatabaseException e) {
\r
234 Logger.defaultLogError(e);
\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
245 private void getMetadata() {
\r
246 if(metadata != null)
\r
248 else if (null == cs) {
\r
249 metadata = new HashMap<String, byte[]>();
\r
253 metadata = cs.getMetadata();
\r
254 if (null == metadata) {
\r
255 ChangeSetIdentifier csid = getChangeSetIdentifier(cs.getId());
\r
257 metadata = csid.getMetadata();
\r
259 } catch (Exception e) {
\r
260 Logger.defaultLogError(e);
\r
262 if (null == metadata)
\r
263 metadata = new HashMap<String, byte[]>();
\r
265 // private static final Charset UTF8 = Charset.forName("UTF-8");
\r
266 // private String toString(byte[] data) {
\r
267 // if (data == null)
\r
269 // CharsetDecoder decoder = UTF8.newDecoder();
\r
270 // ByteBuffer bbuf = ByteBuffer.wrap(data);
\r
271 // CharBuffer cbuf;
\r
272 // String s = null;
\r
274 // cbuf = decoder.decode(bbuf);
\r
275 // s = cbuf.toString();
\r
276 // } catch (CharacterCodingException e) {
\r
281 // .onMalformedInput(CodingErrorAction.REPLACE)
\r
282 // .onUnmappableCharacter(CodingErrorAction.REPLACE)
\r
284 // s = cbuf.toString();
\r
285 // } catch (CharacterCodingException e1) {
\r
286 // return "String conversion error.";
\r
292 public String toString() {
\r
294 return "<no change set>";
\r
296 return "change set " + cs.getId();
\r
299 boolean hasChildren() {
\r
300 if (null == metadata)
\r
302 if (null == cs && metadata.isEmpty())
\r
308 Object[] getChildren() {
\r
309 if (null == metadata)
\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
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
323 CommentMetadata commentMetadata = getMetadata(session, metadata, CommentMetadata.class);
\r
324 if (null != commentMetadata)
\r
325 objects.add(new DisplayElement("Comment", commentMetadata.toString()));
\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
333 if (cs.getId() > 0)
\r
334 objects.add(new ChangeSetDisplayElement("Change Set", session, cs.getId()));
\r
336 return objects.toArray();
\r
338 Image getIdImage() {
\r
339 return Images.getInstance().CHANGE_SET_IMAGE;
\r
341 String getIdText() {
\r
343 return "" + cs.getId();
\r
347 String getDateText() {
\r
348 if (null == metadata)
\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
356 return "<no date>";
\r
358 String getCommentText() {
\r
359 if (null == metadata)
\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
370 return undoMetadata.getHeader() + ": " + t;
\r
373 return "<no comment>";
\r
376 abstract class AbstractColumnLabelProvider extends ColumnLabelProvider {
\r
378 class IdColumnLabelProvider extends AbstractColumnLabelProvider {
\r
380 public void update(ViewerCell cell) {
\r
381 Object element = cell.getElement();
\r
382 if (!(element instanceof TreeElement))
\r
385 TreeElement te = (TreeElement)element;
\r
386 String text = te.getIdText();
\r
388 cell.setText(text);
\r
389 Image image = te.getIdImage();
\r
391 cell.setImage(image);
\r
395 class DateColumnLabelProvider extends AbstractColumnLabelProvider {
\r
397 public void update(ViewerCell cell) {
\r
398 Object element = cell.getElement();
\r
399 if (!(element instanceof TreeElement))
\r
402 TreeElement te = (TreeElement)element;
\r
403 String text = te.getDateText();
\r
405 cell.setText(text);
\r
406 Image image = te.getDateImage();
\r
408 cell.setImage(image);
\r
412 class CommentColumnLabelProvider extends AbstractColumnLabelProvider {
\r
414 public void update(ViewerCell cell) {
\r
415 Object element = cell.getElement();
\r
416 if (!(element instanceof TreeElement))
\r
419 TreeElement te = (TreeElement)element;
\r
420 String text = te.getCommentText();
\r
422 cell.setText(text);
\r
423 Image image = te.getCommentImage();
\r
425 cell.setImage(image);
\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
440 abstract public Object[] getElements(Object inputElement);
\r
442 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
\r
443 this.viewer = viewer;
\r
447 public void dispose() {
\r
448 managementSupport.cancel(this);
\r
449 this.subscribed = false;
\r
452 public void onChanged(long csid) {
\r
453 if (null != viewer && this.subscribed)
\r
457 public boolean hasChildren(Object element) {
\r
458 if (element instanceof TreeElement)
\r
459 return ((TreeElement)element).hasChildren();
\r
463 public Object getParent(Object element) {
\r
467 public Object[] getChildren(Object parentElement) {
\r
468 if (parentElement instanceof TreeElement)
\r
469 return ((TreeElement)parentElement).getChildren();
\r
473 protected void subscribe() {
\r
474 if (this.subscribed)
\r
476 managementSupport.subscribe(this);
\r
477 this.subscribed = true;
\r
479 protected void refresh() {
\r
480 if (viewer == null)
\r
482 SWTUtils.asyncExec(viewer.getControl(), new Runnable() {
\r
484 public void run() {
\r
485 if (!viewer.getControl().isDisposed())
\r