1 /*******************************************************************************
2 * Copyright (c) 2012, 2013 Association for Decentralized Information Management in
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.objmap.internal;
14 import gnu.trove.map.hash.THashMap;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.Collections;
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;
28 public class BidirectionalMapping<Domain, Range> implements IBidirectionalMapping<Domain, Range> {
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>>();
36 ArrayList<BidirectionalLink<Domain, Range>> modifiedDomain = new ArrayList<BidirectionalLink<Domain, Range>>();
37 ArrayList<BidirectionalLink<Domain, Range>> modifiedRange = new ArrayList<BidirectionalLink<Domain, Range>>();
39 private void markDomainModified(BidirectionalLink<Domain, Range> link) {
40 if(!link.domainModified) {
41 link.domainModified = true;
42 modifiedDomain.add(link);
46 private void markRangeModified(BidirectionalLink<Domain, Range> link) {
47 if(!link.rangeModified) {
48 link.rangeModified = true;
49 modifiedRange.add(link);
53 public BidirectionalMapping(IBidirectionalMappingSchema<Domain, Range> schema) {
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);
66 public Set<Domain> getDomain() {
67 return Collections.unmodifiableSet(forwardMap.keySet());
71 public Range get(Domain domainElement) {
72 BidirectionalLink<Domain, Range> link = forwardMap.get(domainElement);
75 return link.rangeElement;
79 public Range map(ReadGraph graph, Domain domainElement) throws MappingException {
80 Range result = get(domainElement);
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);
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);
98 modifiedDomain.clear();
103 public Set<Range> getRange() {
104 return Collections.unmodifiableSet(backwardMap.keySet());
108 public Domain inverseGet(Range rangeElement) {
109 BidirectionalLink<Domain, Range> link = backwardMap.get(rangeElement);
112 return link.domainElement;
116 public Domain inverseMap(WriteGraph graph, Range rangeElement)
117 throws MappingException {
118 Domain result = inverseGet(rangeElement);
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);
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);
136 modifiedDomain.clear();