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