]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.objmap2/src/org/simantics/objmap/internal/BidirectionalMapping.java
Revert "Prime SCL BindingRegistry to shave ~0.5s from startup"
[simantics/platform.git] / bundles / org.simantics.objmap2 / src / org / simantics / objmap / internal / BidirectionalMapping.java
1 /*******************************************************************************
2  * Copyright (c) 2012, 2013 Association for Decentralized Information Management in
3  * 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.objmap.internal;
13
14 import gnu.trove.map.hash.THashMap;
15
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.Collections;
19 import java.util.Set;
20
21 import org.simantics.db.ReadGraph;
22 import org.simantics.db.WriteGraph;
23 import org.simantics.objmap.bidirectional.IBidirectionalLinkType;
24 import org.simantics.objmap.bidirectional.IBidirectionalMapping;
25 import org.simantics.objmap.bidirectional.IBidirectionalMappingSchema;
26 import org.simantics.objmap.exceptions.MappingException;
27
28 public class BidirectionalMapping<Domain, Range> implements IBidirectionalMapping<Domain, Range> {
29
30     IBidirectionalMappingSchema<Domain, Range> schema;
31     THashMap<Domain, BidirectionalLink<Domain, Range>> forwardMap =
32             new THashMap<Domain, BidirectionalLink<Domain, Range>>();
33     THashMap<Range, BidirectionalLink<Domain, Range>> backwardMap =
34             new THashMap<Range, BidirectionalLink<Domain, Range>>();
35     
36     ArrayList<BidirectionalLink<Domain, Range>> modifiedDomain = new ArrayList<BidirectionalLink<Domain, Range>>();
37     ArrayList<BidirectionalLink<Domain, Range>> modifiedRange = new ArrayList<BidirectionalLink<Domain, Range>>();
38     
39     private void markDomainModified(BidirectionalLink<Domain, Range> link) {
40         if(!link.domainModified) {
41             link.domainModified = true;
42             modifiedDomain.add(link);
43         }
44     }
45     
46     private void markRangeModified(BidirectionalLink<Domain, Range> link) {
47         if(!link.rangeModified) {
48             link.rangeModified = true;
49             modifiedRange.add(link);
50         }
51     }
52     
53     public BidirectionalMapping(IBidirectionalMappingSchema<Domain, Range> schema) {
54         this.schema = schema;
55     }
56
57     private BidirectionalLink<Domain, Range> addLink(IBidirectionalLinkType<Domain, Range> linkType, Domain domainElement, Range rangeElement) {
58         BidirectionalLink<Domain, Range> link = 
59                 new BidirectionalLink<Domain, Range>(linkType, domainElement, rangeElement);
60         forwardMap.put(domainElement, link);
61         backwardMap.put(rangeElement, link);
62         return link;
63     }
64     
65     @Override
66     public Set<Domain> getDomain() {
67         return Collections.unmodifiableSet(forwardMap.keySet());
68     }
69
70     @Override
71     public Range get(Domain domainElement) {
72         BidirectionalLink<Domain, Range> link = forwardMap.get(domainElement);
73         if(link == null)
74             return null;
75         return link.rangeElement;
76     }
77
78     @Override
79     public Range map(ReadGraph graph, Domain domainElement) throws MappingException {
80         Range result = get(domainElement);
81         if(result == null) {
82             IBidirectionalLinkType<Domain, Range> linkType = 
83                     schema.linkTypeOfDomainElement(graph, domainElement);
84             Range rangeElement = linkType.createRangeElement(graph, domainElement);
85             addLink(linkType, domainElement, rangeElement);
86             linkType.createRange(graph, this, domainElement, rangeElement);
87         }
88         return result;
89     }
90     
91     public Collection<Range> updateRange(ReadGraph graph) throws MappingException {
92         ArrayList<Range> updated = new ArrayList<Range>(Math.max(10, modifiedDomain.size())); 
93         for(BidirectionalLink<Domain, Range> link : modifiedDomain) {
94             link.domainModified = false;
95             if(link.linkType.updateRange(graph, this, link.domainElement, link.rangeElement))
96                 updated.add(link.rangeElement);
97         }
98         modifiedDomain.clear();
99         return updated;        
100     }
101
102     @Override
103     public Set<Range> getRange() {
104         return Collections.unmodifiableSet(backwardMap.keySet());
105     }
106
107     @Override
108     public Domain inverseGet(Range rangeElement) {
109         BidirectionalLink<Domain, Range> link = backwardMap.get(rangeElement);
110         if(link == null)
111             return null;
112         return link.domainElement;
113     }
114
115     @Override
116     public Domain inverseMap(WriteGraph graph, Range rangeElement)
117             throws MappingException {
118         Domain result = inverseGet(rangeElement);
119         if(result == null) {
120             IBidirectionalLinkType<Domain, Range> linkType = 
121                     schema.linkTypeOfRangeElement(graph, rangeElement);
122             Domain domainElement = linkType.createDomainElement(graph, rangeElement);
123             addLink(linkType, domainElement, rangeElement);
124             linkType.createDomain(graph, this, domainElement, rangeElement);
125         }
126         return result;
127     }
128     
129     public Collection<Domain> updateDomain(WriteGraph graph) throws MappingException {
130         ArrayList<Domain> updated = new ArrayList<Domain>(Math.max(10, modifiedRange.size())); 
131         for(BidirectionalLink<Domain, Range> link : modifiedRange) {
132             link.rangeModified = false;
133             if(link.linkType.updateDomain(graph, this, link.domainElement, link.rangeElement))
134                 updated.add(link.domainElement);
135         }
136         modifiedDomain.clear();
137         return updated;        
138     }
139
140 }