]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/changeset/MetadataUtils.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / changeset / MetadataUtils.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.layer0.changeset;
13
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashMap;
17 import java.util.Map;
18 import java.util.TreeMap;
19
20 import org.simantics.db.ChangeSetIdentifier;
21 import org.simantics.db.ReadGraph;
22 import org.simantics.db.Resource;
23 import org.simantics.db.WriteGraph;
24 import org.simantics.db.common.UndoMetadata;
25 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
26 import org.simantics.db.exception.DatabaseException;
27 import org.simantics.db.layer0.genericrelation.DependencyChanges;
28 import org.simantics.db.layer0.genericrelation.DependencyChanges.Change;
29 import org.simantics.db.layer0.request.IsLinkedTo;
30 import org.simantics.db.service.ManagementSupport;
31
32 public class MetadataUtils {
33         
34         public static final boolean DEBUG = false;
35         public static final boolean DEBUG_IDS = false;
36
37         public static Map<Long, Map<String,byte[]>> getMetadatas(ReadGraph graph, ManagementSupport support, long fromRevisionId, long toRevisionId) throws DatabaseException {
38
39             TreeMap<Long, Map<String,byte[]>> result = new TreeMap<Long, Map<String,byte[]>>(); 
40                     
41             Collection<ChangeSetIdentifier> csis = support.getChangeSetIdentifiers(fromRevisionId, toRevisionId);
42         for(ChangeSetIdentifier csi : csis) {
43             if(csi.getId() < fromRevisionId) {
44                 System.err.println("ManagementSupport.getChangeSetIdentifiers returned identifiers outside of the requested range.");
45                 continue;
46             }
47             Map<String,byte[]> metadata = csi.getMetadata();
48             if(metadata != null) result.put(csi.getId(), metadata);
49         }
50         long toBeRevision = support.getHeadRevisionId()+1;
51         if(toBeRevision >= fromRevisionId && toBeRevision <= toRevisionId) {
52             if(graph instanceof WriteGraph) {
53                 WriteGraph writeGraph = (WriteGraph)graph;
54                 Map<String,byte[]> metadata = writeGraph.getMetadata();
55                 if(metadata != null)
56                     result.put(toBeRevision, metadata);
57             }
58         }
59         
60         return result;
61             
62         }
63         
64         public static Map<Resource, Collection<Change>> getDependencyChangesFrom(ReadGraph graph, long revisionId) throws DatabaseException {
65                 ManagementSupport support = graph.getService(ManagementSupport.class);
66                 
67         Map<Resource, Collection<Change>> result = new HashMap<Resource, Collection<Change>>();
68                 Map<Long, Map<String,byte[]>> metadatas = getMetadatas(graph, support, revisionId, Long.MAX_VALUE);
69                 
70                 for(Map.Entry<Long, Map<String,byte[]>> e : metadatas.entrySet()) {
71                     long csid = e.getKey();
72                         Map<String,byte[]> metadata = e.getValue();
73                         if(metadata != null) {
74                                 byte[] changesData = metadata.get(DependencyChanges.class.getName());
75                                 if(changesData != null && changesData.length > 0) {
76                                         DependencyChanges changes = DependencyChanges.deserialise(graph.getSession(), changesData);
77                                         if (changes == null)
78                                                 continue;
79                                         if(DEBUG_IDS) System.err.println("-DependencyChanges[" + csid + "]");
80                                         for(Map.Entry<Resource, Change[]> entry : changes.modelChanges.entrySet()) {
81                                                 Collection<Change> list = result.get(entry.getKey());
82                                                 if(list == null) {
83                                                         list = new ArrayList<Change>();
84                                                         result.put(entry.getKey(), list);
85                                                 }
86                                                 for(Change c : entry.getValue()) {
87                                                         if(DEBUG) System.err.println("-" + c);
88                                                         list.add(c);
89                                                 }
90                                         }
91                                 }
92                         }
93                 }
94                 return result;
95         }
96     
97         public static void visitDependencyChangesFrom2(ReadGraph graph,
98                         Resource model, Change[] changes, ChangeVisitor changeVisitor) throws DatabaseException {
99         for(Change change : changes) {
100                 changeVisitor.visit(graph, change, false);
101         }
102         }
103
104     /**
105      * Finds all changes made to the given {@code model} from the given revision and calls 
106      * the {@code visitor} for them.
107      */
108     public static void visitDependencyChangesFrom(ReadGraph graph, Resource model, long fromRevision,
109             ChangeVisitor visitor) throws DatabaseException {
110         visitDependencyChangesBetween(graph, model, fromRevision, Long.MAX_VALUE, visitor, false);
111     }
112
113     private static void visitDependencyChangesBetween(ReadGraph graph, Resource model, long fromRevision, long toRevision,
114             ChangeVisitor visitor, boolean inverted) throws DatabaseException {
115         ManagementSupport support = graph.getService(ManagementSupport.class);
116 //        System.err.println("visitDependencyChangesBetween " + fromRevision + " " + toRevision);
117 //        Collection<ChangeSetIdentifier> csis = support.getChangeSetIdentifiers(fromRevision, toRevision);
118         
119         Map<Long, Map<String,byte[]>> metadatas = getMetadatas(graph, support, fromRevision, toRevision);
120
121 //        Map<Resource, Collection<Change>> result = new HashMap<Resource, Collection<Change>>();
122 //        Map<Long, Map<String,byte[]>> metadatas = getMetadatas(graph, support, revisionId, Long.MAX_VALUE);
123         
124         for(Map.Entry<Long, Map<String,byte[]>> e : metadatas.entrySet()) {
125
126             Map<String,byte[]> metadata = e.getValue();
127
128             browseChanges: {
129                 byte[] changesData = metadata.get(DependencyChanges.class.getName());
130                 if(changesData == null || changesData.length == 0) 
131                     break browseChanges;
132                 DependencyChanges changes = DependencyChanges.deserialise(graph.getSession(), changesData);
133                 if (changes == null)
134                     break browseChanges;
135                 for(Map.Entry<Resource, Change[]> entry : changes.modelChanges.entrySet())
136                     if(graph.syncRequest(new IsLinkedTo(model, entry.getKey()),
137                             TransientCacheListener.<Boolean>instance()))
138                         for(Change change : entry.getValue())
139                             visitor.visit(graph, change, inverted);
140             }
141             
142             byte[] undoMetadata = metadata.get(UndoMetadata.class.getName());
143             if(undoMetadata != null && undoMetadata.length != 0) { 
144                 UndoMetadata undo = UndoMetadata.deserialise(graph.getSession(), undoMetadata);
145                 visitDependencyChangesBetween(graph, model, undo.getBeginCSId(), undo.getEndCSId(), visitor, 
146                         undo.isRedo() ? inverted : !inverted);
147             }
148         }
149     }
150
151 }