1 /*******************************************************************************
\r
2 * Copyright (c) 2012, 2013 Association for Decentralized Information Management in
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.objmap.internal;
\r
14 import gnu.trove.map.hash.THashMap;
\r
16 import java.util.ArrayList;
\r
17 import java.util.Collection;
\r
18 import java.util.Collections;
\r
19 import java.util.Set;
\r
21 import org.simantics.db.ReadGraph;
\r
22 import org.simantics.db.WriteGraph;
\r
23 import org.simantics.objmap.bidirectional.IBidirectionalLinkType;
\r
24 import org.simantics.objmap.bidirectional.IBidirectionalMapping;
\r
25 import org.simantics.objmap.bidirectional.IBidirectionalMappingSchema;
\r
26 import org.simantics.objmap.exceptions.MappingException;
\r
28 public class BidirectionalMapping<Domain, Range> implements IBidirectionalMapping<Domain, Range> {
\r
30 IBidirectionalMappingSchema<Domain, Range> schema;
\r
31 THashMap<Domain, BidirectionalLink<Domain, Range>> forwardMap =
\r
32 new THashMap<Domain, BidirectionalLink<Domain, Range>>();
\r
33 THashMap<Range, BidirectionalLink<Domain, Range>> backwardMap =
\r
34 new THashMap<Range, BidirectionalLink<Domain, Range>>();
\r
36 ArrayList<BidirectionalLink<Domain, Range>> modifiedDomain = new ArrayList<BidirectionalLink<Domain, Range>>();
\r
37 ArrayList<BidirectionalLink<Domain, Range>> modifiedRange = new ArrayList<BidirectionalLink<Domain, Range>>();
\r
39 private void markDomainModified(BidirectionalLink<Domain, Range> link) {
\r
40 if(!link.domainModified) {
\r
41 link.domainModified = true;
\r
42 modifiedDomain.add(link);
\r
46 private void markRangeModified(BidirectionalLink<Domain, Range> link) {
\r
47 if(!link.rangeModified) {
\r
48 link.rangeModified = true;
\r
49 modifiedRange.add(link);
\r
53 public BidirectionalMapping(IBidirectionalMappingSchema<Domain, Range> schema) {
\r
54 this.schema = schema;
\r
57 private BidirectionalLink<Domain, Range> addLink(IBidirectionalLinkType<Domain, Range> linkType, Domain domainElement, Range rangeElement) {
\r
58 BidirectionalLink<Domain, Range> link =
\r
59 new BidirectionalLink<Domain, Range>(linkType, domainElement, rangeElement);
\r
60 forwardMap.put(domainElement, link);
\r
61 backwardMap.put(rangeElement, link);
\r
66 public Set<Domain> getDomain() {
\r
67 return Collections.unmodifiableSet(forwardMap.keySet());
\r
71 public Range get(Domain domainElement) {
\r
72 BidirectionalLink<Domain, Range> link = forwardMap.get(domainElement);
\r
75 return link.rangeElement;
\r
79 public Range map(ReadGraph graph, Domain domainElement) throws MappingException {
\r
80 Range result = get(domainElement);
\r
81 if(result == null) {
\r
82 IBidirectionalLinkType<Domain, Range> linkType =
\r
83 schema.linkTypeOfDomainElement(graph, domainElement);
\r
84 Range rangeElement = linkType.createRangeElement(graph, domainElement);
\r
85 addLink(linkType, domainElement, rangeElement);
\r
86 linkType.createRange(graph, this, domainElement, rangeElement);
\r
91 public Collection<Range> updateRange(ReadGraph graph) throws MappingException {
\r
92 ArrayList<Range> updated = new ArrayList<Range>(Math.max(10, modifiedDomain.size()));
\r
93 for(BidirectionalLink<Domain, Range> link : modifiedDomain) {
\r
94 link.domainModified = false;
\r
95 if(link.linkType.updateRange(graph, this, link.domainElement, link.rangeElement))
\r
96 updated.add(link.rangeElement);
\r
98 modifiedDomain.clear();
\r
103 public Set<Range> getRange() {
\r
104 return Collections.unmodifiableSet(backwardMap.keySet());
\r
108 public Domain inverseGet(Range rangeElement) {
\r
109 BidirectionalLink<Domain, Range> link = backwardMap.get(rangeElement);
\r
112 return link.domainElement;
\r
116 public Domain inverseMap(WriteGraph graph, Range rangeElement)
\r
117 throws MappingException {
\r
118 Domain result = inverseGet(rangeElement);
\r
119 if(result == null) {
\r
120 IBidirectionalLinkType<Domain, Range> linkType =
\r
121 schema.linkTypeOfRangeElement(graph, rangeElement);
\r
122 Domain domainElement = linkType.createDomainElement(graph, rangeElement);
\r
123 addLink(linkType, domainElement, rangeElement);
\r
124 linkType.createDomain(graph, this, domainElement, rangeElement);
\r
129 public Collection<Domain> updateDomain(WriteGraph graph) throws MappingException {
\r
130 ArrayList<Domain> updated = new ArrayList<Domain>(Math.max(10, modifiedRange.size()));
\r
131 for(BidirectionalLink<Domain, Range> link : modifiedRange) {
\r
132 link.rangeModified = false;
\r
133 if(link.linkType.updateDomain(graph, this, link.domainElement, link.rangeElement))
\r
134 updated.add(link.domainElement);
\r
136 modifiedDomain.clear();
\r