1 package org.simantics.objmap.internal;
\r
3 import gnu.trove.map.hash.THashMap;
\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
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
17 public class BidirectionalMapping<Domain, Range> implements IBidirectionalMapping<Domain, Range> {
\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
25 ArrayList<BidirectionalLink<Domain, Range>> modifiedDomain = new ArrayList<BidirectionalLink<Domain, Range>>();
\r
26 ArrayList<BidirectionalLink<Domain, Range>> modifiedRange = new ArrayList<BidirectionalLink<Domain, Range>>();
\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
35 private void markRangeModified(BidirectionalLink<Domain, Range> link) {
\r
36 if(!link.rangeModified) {
\r
37 link.rangeModified = true;
\r
38 modifiedRange.add(link);
\r
42 public BidirectionalMapping(IBidirectionalMappingSchema<Domain, Range> schema) {
\r
43 this.schema = schema;
\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
55 public Set<Domain> getDomain() {
\r
56 return Collections.unmodifiableSet(forwardMap.keySet());
\r
60 public Range get(Domain domainElement) {
\r
61 BidirectionalLink<Domain, Range> link = forwardMap.get(domainElement);
\r
64 return link.rangeElement;
\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
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
87 modifiedDomain.clear();
\r
92 public Set<Range> getRange() {
\r
93 return Collections.unmodifiableSet(backwardMap.keySet());
\r
97 public Domain inverseGet(Range rangeElement) {
\r
98 BidirectionalLink<Domain, Range> link = backwardMap.get(rangeElement);
\r
101 return link.domainElement;
\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
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
125 modifiedDomain.clear();
\r