-/*******************************************************************************\r
- * Copyright (c) 2007, 2013 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.objmap.graph.impl;\r
-\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-\r
-import java.util.AbstractSet;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import java.util.Set;\r
-\r
-import org.apache.log4j.Logger;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.exception.DatabaseException;\r
-\r
-import org.simantics.objmap.backward.IBackwardMapping;\r
-import org.simantics.objmap.exceptions.MappingException;\r
-import org.simantics.objmap.forward.IForwardMapping;\r
-import org.simantics.objmap.graph.IMapping;\r
-import org.simantics.objmap.graph.IMappingListener;\r
-import org.simantics.objmap.graph.schema.ILinkType;\r
-import org.simantics.objmap.graph.schema.IMappingSchema;\r
-\r
-/**\r
- * An implementation of IMapping. The class should not be created\r
- * directly but using methods in Mappings.\r
- * @see org.simantics.objmap.graph.Mappings\r
- * @author Hannu Niemistö\r
- */\r
-public class Mapping<Domain, Range> implements IMapping<Domain, Range> {\r
-\r
- static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
- \r
- \r
- IMappingSchema<Domain, Range> schema;\r
- \r
- THashMap<Domain, Link<Domain,Range>> domain = new THashMap<Domain, Link<Domain,Range>>();\r
- THashMap<Range, Link<Domain,Range>> range = new THashMap<Range, Link<Domain,Range>>();\r
- ArrayList<IMappingListener> listeners = new ArrayList<IMappingListener>();\r
-\r
- ArrayList<Link<Domain,Range>> modifiedDomainLinks = new ArrayList<Link<Domain,Range>>();\r
- ArrayList<Link<Domain,Range>> modifiedRangeLinks = new ArrayList<Link<Domain,Range>>();\r
-\r
- boolean disposed = false;\r
- \r
- boolean listensDomain; \r
- \r
- public Mapping(IMappingSchema<Domain, Range> schema, boolean listensDomain) {\r
- this.schema = schema;\r
- this.listensDomain = listensDomain;\r
- }\r
- \r
- private void removeLink(Link<Domain,Range> link) {\r
- if(link.domainModified)\r
- modifiedDomainLinks.remove(link);\r
- if(link.rangeModified)\r
- modifiedRangeLinks.remove(link);\r
- link.removed = true;\r
- }\r
- \r
- private void createDomain(WriteGraph g, Link<Domain,Range> link) throws MappingException {\r
- LOGGER.info(" createDomain for " + link.rangeElement);\r
- ILinkType<Domain,Range> type = schema.linkTypeOfRangeElement(link.rangeElement);\r
- Domain domainElement = type.createDomainElement(g, link.rangeElement);\r
- link.type = type;\r
- link.domainElement = domainElement;\r
- domain.put(domainElement, link);\r
- type.createDomain(g, new RangeToDomain(g), domainElement, link.rangeElement);\r
- \r
- // TODO Should we do this only if the mapping is listening?\r
- domainModified(link);\r
- }\r
- \r
- private void createRange(ReadGraph g, Link<Domain,Range> link) throws MappingException {\r
- ILinkType<Domain,Range> type = schema.linkTypeOfDomainElement(g, link.domainElement); \r
- Range rangeElement = type.createRangeElement(g, link.domainElement);\r
- \r
- link.type = type;\r
- link.rangeElement = rangeElement;\r
- range.put(rangeElement, link);\r
- type.createRange(g, new DomainToRange(g), link.domainElement, rangeElement);\r
- }\r
- \r
- Set<Domain> domainSet = new AbstractSet<Domain>() {\r
-\r
- public boolean add(Domain e) {\r
- if(domain.containsKey(e))\r
- return false;\r
- Link<Domain,Range> link = new Link<Domain,Range>(null, e, null);\r
- domain.put(e, link);\r
- modifiedDomainLinks.add(link);\r
- return true;\r
- }\r
- \r
- public boolean contains(Object o) {\r
- return domain.contains(o);\r
- }\r
- \r
- public boolean remove(Object o) {\r
- Link<Domain,Range> link = domain.remove(o); \r
- if(link == null)\r
- return false;\r
- removeLink(link);\r
- if(link.rangeElement != null)\r
- range.remove(link.rangeElement);\r
- return true; \r
- }\r
- \r
- @Override\r
- public Iterator<Domain> iterator() {\r
- // FIXME does not implement Iterator.remove correctly\r
- return domain.keySet().iterator();\r
- }\r
-\r
- @Override\r
- public int size() {\r
- return domain.size();\r
- }\r
- \r
- };\r
- \r
- Set<Range> rangeSet = new AbstractSet<Range>() {\r
-\r
- public boolean add(Range e) {\r
- if(range.containsKey(e))\r
- return false;\r
- Link<Domain,Range> link = new Link<Domain,Range>(null, null, e);\r
- range.put(e, link);\r
- modifiedRangeLinks.add(link);\r
- return true;\r
- }\r
- \r
- public boolean contains(Object o) {\r
- return range.contains(o);\r
- }\r
- \r
- public boolean remove(Object o) {\r
- Link<Domain,Range> link = range.remove(o); \r
- if(link == null)\r
- return false;\r
- removeLink(link);\r
- if(link.domainElement != null)\r
- domain.remove(link.domainElement);\r
- return true;\r
- }\r
- \r
- @Override\r
- public Iterator<Range> iterator() {\r
- // FIXME does not implement Iterator.remove correctly\r
- return range.keySet().iterator();\r
- }\r
-\r
- @Override\r
- public int size() {\r
- return range.size();\r
- }\r
- \r
- };\r
- \r
- class DomainToRange implements IForwardMapping<Domain, Range> {\r
-\r
- ReadGraph g;\r
- \r
- public DomainToRange(ReadGraph g) {\r
- this.g = g;\r
- }\r
-\r
- @Override\r
- public Range get(Domain element) {\r
- Link<Domain,Range> link = domain.get(element);\r
- if (link != null)\r
- return link.rangeElement;\r
- return null;\r
- \r
- }\r
- \r
- @Override\r
- public Range map(ReadGraph graph, Domain element)\r
- throws MappingException {\r
- Link<Domain,Range> link = domain.get(element);\r
- if(link == null) {\r
- link = new Link<Domain,Range>(null, element, null);\r
- link.domainModified = true;\r
- modifiedDomainLinks.add(link);\r
- domain.put(element, link); \r
- createRange(g, link); \r
- }\r
- else if(link.type == null) \r
- createRange(g, link);\r
- return link.rangeElement;\r
- }\r
- \r
- @Override\r
- public Set<Domain> getDomain() {\r
- return domain.keySet();\r
- }\r
- \r
- };\r
- \r
- class RangeToDomain extends DomainToRange implements IBackwardMapping<Domain, Range> {\r
-\r
- WriteGraph g;\r
- \r
- public RangeToDomain(WriteGraph g) {\r
- super(g);\r
- this.g = g;\r
- }\r
- @Override\r
- public Domain inverseGet(Range element) {\r
- \r
- Link<Domain,Range> link = range.get(element);\r
- if(link != null)\r
- return link.domainElement;\r
- return null;\r
- }\r
- \r
- @Override\r
- public Domain inverseMap(WriteGraph graph, Range element)\r
- throws MappingException {\r
- Link<Domain,Range> link = range.get(element);\r
- if(link == null) {\r
- link = new Link<Domain,Range>(null, null, element);\r
- link.rangeModified = true;\r
- modifiedRangeLinks.add(link);\r
- range.put(element, link);\r
- createDomain(g, link); \r
- }\r
- else if(link.type == null)\r
- createDomain(g, link);\r
- return link.domainElement;\r
- }\r
- \r
- \r
- @Override\r
- public Set<Range> getRange() {\r
- return range.keySet();\r
- }\r
- };\r
- \r
- @Override\r
- public Set<Domain> getDomain() {\r
- return domainSet;\r
- }\r
- \r
- @Override\r
- public Set<Range> getRange() {\r
- return rangeSet;\r
- }\r
- \r
- \r
- @Override\r
- public synchronized Collection<Domain> updateDomain(WriteGraph g) throws MappingException {\r
- LOGGER.info("Mapping.updateDomain");\r
- RangeToDomain map = new RangeToDomain(g);\r
- ArrayList<Domain> updated = new ArrayList<Domain>();\r
- while(!modifiedRangeLinks.isEmpty()) {\r
- LOGGER.info(" modifiedRangeLinks.size() = " + modifiedRangeLinks.size());\r
- \r
- Link<Domain,Range> link = modifiedRangeLinks.remove(modifiedRangeLinks.size()-1);\r
- link.rangeModified = false;\r
- /*if(link.domainModified) {\r
- link.domainModified = false;\r
- modifiedDomainLinks.remove(link);\r
- }*/\r
- \r
- if(link.type == null) {\r
- createDomain(g, link);\r
- }\r
- \r
- if(link.type.updateDomain(g, map, link.domainElement, link.rangeElement))\r
- updated.add(link.domainElement);\r
- } \r
- if (listensDomain)\r
- updateRange(g); //FIXME: without this listening would stop. \r
- return updated;\r
- }\r
- \r
- @Override\r
- public synchronized Collection<Range> updateRange(ReadGraph g) throws MappingException {\r
- LOGGER.info("Mapping.updateRange");\r
- DomainToRange map = new DomainToRange(g);\r
- ArrayList<Range> updated = new ArrayList<Range>();\r
- while(!modifiedDomainLinks.isEmpty()) { \r
- LOGGER.info(" modifiedDomainLinks.size() = " + modifiedDomainLinks.size());\r
- \r
- Link<Domain,Range> link = modifiedDomainLinks.remove(modifiedDomainLinks.size()-1);\r
- link.domainModified = false;\r
- /*if(link.rangeModified) {\r
- link.rangeModified = false;\r
- modifiedRangeLinks.remove(link);\r
- }*/\r
- \r
- if(link.type == null) {\r
- createRange(g, link);\r
- }\r
- \r
- if(listensDomain) {\r
- RangeUpdateRequest<Domain,Range> request = new RangeUpdateRequest<Domain,Range>(link, map, this);\r
- try {\r
- g.syncRequest(request, request);\r
- } catch (DatabaseException e) {\r
- throw new MappingException(e);\r
- }\r
- // TODO check if really modified\r
- updated.add(link.rangeElement);\r
- }\r
- else\r
- if(link.type.updateRange(g, map, link.domainElement, link.rangeElement))\r
- updated.add(link.rangeElement);\r
- } \r
- return updated;\r
- }\r
-\r
- @Override\r
- public Range get(Domain domainElement) {\r
- Link<Domain,Range> link = domain.get(domainElement);\r
- if(link == null)\r
- return null;\r
- return link.rangeElement;\r
- }\r
-\r
- @Override\r
- public Domain inverseGet(Range rangeElement) {\r
- Link<Domain,Range> link = range.get(rangeElement);\r
- if(link == null)\r
- return null;\r
- return link.domainElement;\r
- }\r
-\r
- @Override\r
- public Domain inverseMap(WriteGraph g, Range rangeElement) throws MappingException {\r
- getRange().add(rangeElement);\r
- updateDomain(g);\r
- return inverseGet(rangeElement);\r
- }\r
-\r
- @Override\r
- public Range map(ReadGraph g, Domain domainElement) throws MappingException {\r
- getDomain().add(domainElement);\r
- updateRange(g);\r
- return get(domainElement);\r
- }\r
-\r
- void domainModified(Link<Domain,Range> link) {\r
- if(!link.domainModified) { \r
- synchronized(modifiedDomainLinks) {\r
- LOGGER.info(" domainModified for " + link.rangeElement);\r
- link.domainModified = true;\r
- modifiedDomainLinks.add(link);\r
- if(modifiedDomainLinks.size() == 1) {\r
- for(IMappingListener listener : listeners)\r
- listener.domainModified();\r
- }\r
- }\r
- }\r
- }\r
- \r
- @Override\r
- public void domainModified(Domain domainElement) {\r
- Link<Domain,Range> link = domain.get(domainElement);\r
- if(link != null)\r
- domainModified(link);\r
- }\r
-\r
- void rangeModified(Link<Domain,Range> link) {\r
- if(!link.rangeModified) {\r
- synchronized(modifiedRangeLinks) {\r
- link.rangeModified = true;\r
- modifiedRangeLinks.add(link);\r
- if(modifiedRangeLinks.size() == 1) {\r
- for(IMappingListener listener : listeners)\r
- listener.rangeModified();\r
- }\r
- }\r
- }\r
- }\r
- \r
- @Override\r
- public void rangeModified(Range rangeElement) {\r
- Link<Domain,Range> link = range.get(rangeElement);\r
- if(link != null)\r
- rangeModified(link);\r
- }\r
-\r
- @Override\r
- public boolean isDomainModified() {\r
- return !modifiedDomainLinks.isEmpty();\r
- }\r
-\r
- @Override\r
- public boolean isRangeModified() {\r
- return !modifiedRangeLinks.isEmpty();\r
- }\r
- \r
- @Override\r
- public Collection<Domain> getDomainModified() {\r
- List<Domain> list = new ArrayList<Domain>(modifiedDomainLinks.size());\r
- for (Link<Domain, Range> link : modifiedDomainLinks)\r
- list.add(link.domainElement);\r
- return list;\r
- \r
- }\r
- \r
- @Override\r
- public Collection<Range> getRangeModified() {\r
- List<Range> list = new ArrayList<Range>(modifiedRangeLinks.size());\r
- for (Link<Domain, Range> link : modifiedRangeLinks)\r
- list.add(link.rangeElement);\r
- return list;\r
- }\r
-\r
- @Override\r
- public void addMappingListener(IMappingListener listener) {\r
- listeners.add(listener);\r
- }\r
-\r
- @Override\r
- public void removeMappingListener(IMappingListener listener) {\r
- listeners.remove(listener); \r
- }\r
-\r
- @Override\r
- public Collection<Domain> getConflictingDomainElements() {\r
- ArrayList<Domain> result = new ArrayList<Domain>();\r
- if(modifiedDomainLinks.size() < modifiedRangeLinks.size()) {\r
- for(Link<Domain,Range> link : modifiedDomainLinks)\r
- if(link.rangeModified)\r
- result.add(link.domainElement);\r
- }\r
- else {\r
- for(Link<Domain,Range> link : modifiedRangeLinks)\r
- if(link.domainModified)\r
- result.add(link.domainElement);\r
- }\r
- return result;\r
- }\r
-\r
- @Override\r
- public Collection<Range> getConflictingRangeElements() {\r
- ArrayList<Range> result = new ArrayList<Range>();\r
- if(modifiedDomainLinks.size() < modifiedRangeLinks.size()) {\r
- for(Link<Domain,Range> link : modifiedDomainLinks)\r
- if(link.rangeModified)\r
- result.add(link.rangeElement);\r
- }\r
- else {\r
- for(Link<Domain,Range> link : modifiedRangeLinks)\r
- if(link.domainModified)\r
- result.add(link.rangeElement);\r
- }\r
- return result;\r
- }\r
-\r
- @Override\r
- public void dispose() {\r
- disposed = true;\r
- }\r
- \r
- public boolean isDisposed() {\r
- return disposed;\r
- }\r
- \r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2013 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.objmap.graph.impl;
+
+
+import gnu.trove.map.hash.THashMap;
+
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.exception.DatabaseException;
+
+import org.simantics.objmap.backward.IBackwardMapping;
+import org.simantics.objmap.exceptions.MappingException;
+import org.simantics.objmap.forward.IForwardMapping;
+import org.simantics.objmap.graph.IMapping;
+import org.simantics.objmap.graph.IMappingListener;
+import org.simantics.objmap.graph.schema.ILinkType;
+import org.simantics.objmap.graph.schema.IMappingSchema;
+
+/**
+ * An implementation of IMapping. The class should not be created
+ * directly but using methods in Mappings.
+ * @see org.simantics.objmap.graph.Mappings
+ * @author Hannu Niemistö
+ */
+public class Mapping<Domain, Range> implements IMapping<Domain, Range> {
+
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");
+
+
+ IMappingSchema<Domain, Range> schema;
+
+ THashMap<Domain, Link<Domain,Range>> domain = new THashMap<Domain, Link<Domain,Range>>();
+ THashMap<Range, Link<Domain,Range>> range = new THashMap<Range, Link<Domain,Range>>();
+ ArrayList<IMappingListener> listeners = new ArrayList<IMappingListener>();
+
+ ArrayList<Link<Domain,Range>> modifiedDomainLinks = new ArrayList<Link<Domain,Range>>();
+ ArrayList<Link<Domain,Range>> modifiedRangeLinks = new ArrayList<Link<Domain,Range>>();
+
+ boolean disposed = false;
+
+ boolean listensDomain;
+
+ public Mapping(IMappingSchema<Domain, Range> schema, boolean listensDomain) {
+ this.schema = schema;
+ this.listensDomain = listensDomain;
+ }
+
+ private void removeLink(Link<Domain,Range> link) {
+ if(link.domainModified)
+ modifiedDomainLinks.remove(link);
+ if(link.rangeModified)
+ modifiedRangeLinks.remove(link);
+ link.removed = true;
+ }
+
+ private void createDomain(WriteGraph g, Link<Domain,Range> link) throws MappingException {
+ LOGGER.info(" createDomain for " + link.rangeElement);
+ ILinkType<Domain,Range> type = schema.linkTypeOfRangeElement(link.rangeElement);
+ Domain domainElement = type.createDomainElement(g, link.rangeElement);
+ link.type = type;
+ link.domainElement = domainElement;
+ domain.put(domainElement, link);
+ type.createDomain(g, new RangeToDomain(g), domainElement, link.rangeElement);
+
+ // TODO Should we do this only if the mapping is listening?
+ domainModified(link);
+ }
+
+ private void createRange(ReadGraph g, Link<Domain,Range> link) throws MappingException {
+ ILinkType<Domain,Range> type = schema.linkTypeOfDomainElement(g, link.domainElement);
+ Range rangeElement = type.createRangeElement(g, link.domainElement);
+
+ link.type = type;
+ link.rangeElement = rangeElement;
+ range.put(rangeElement, link);
+ type.createRange(g, new DomainToRange(g), link.domainElement, rangeElement);
+ }
+
+ Set<Domain> domainSet = new AbstractSet<Domain>() {
+
+ public boolean add(Domain e) {
+ if(domain.containsKey(e))
+ return false;
+ Link<Domain,Range> link = new Link<Domain,Range>(null, e, null);
+ domain.put(e, link);
+ modifiedDomainLinks.add(link);
+ return true;
+ }
+
+ public boolean contains(Object o) {
+ return domain.contains(o);
+ }
+
+ public boolean remove(Object o) {
+ Link<Domain,Range> link = domain.remove(o);
+ if(link == null)
+ return false;
+ removeLink(link);
+ if(link.rangeElement != null)
+ range.remove(link.rangeElement);
+ return true;
+ }
+
+ @Override
+ public Iterator<Domain> iterator() {
+ // FIXME does not implement Iterator.remove correctly
+ return domain.keySet().iterator();
+ }
+
+ @Override
+ public int size() {
+ return domain.size();
+ }
+
+ };
+
+ Set<Range> rangeSet = new AbstractSet<Range>() {
+
+ public boolean add(Range e) {
+ if(range.containsKey(e))
+ return false;
+ Link<Domain,Range> link = new Link<Domain,Range>(null, null, e);
+ range.put(e, link);
+ modifiedRangeLinks.add(link);
+ return true;
+ }
+
+ public boolean contains(Object o) {
+ return range.contains(o);
+ }
+
+ public boolean remove(Object o) {
+ Link<Domain,Range> link = range.remove(o);
+ if(link == null)
+ return false;
+ removeLink(link);
+ if(link.domainElement != null)
+ domain.remove(link.domainElement);
+ return true;
+ }
+
+ @Override
+ public Iterator<Range> iterator() {
+ // FIXME does not implement Iterator.remove correctly
+ return range.keySet().iterator();
+ }
+
+ @Override
+ public int size() {
+ return range.size();
+ }
+
+ };
+
+ class DomainToRange implements IForwardMapping<Domain, Range> {
+
+ ReadGraph g;
+
+ public DomainToRange(ReadGraph g) {
+ this.g = g;
+ }
+
+ @Override
+ public Range get(Domain element) {
+ Link<Domain,Range> link = domain.get(element);
+ if (link != null)
+ return link.rangeElement;
+ return null;
+
+ }
+
+ @Override
+ public Range map(ReadGraph graph, Domain element)
+ throws MappingException {
+ Link<Domain,Range> link = domain.get(element);
+ if(link == null) {
+ link = new Link<Domain,Range>(null, element, null);
+ link.domainModified = true;
+ modifiedDomainLinks.add(link);
+ domain.put(element, link);
+ createRange(g, link);
+ }
+ else if(link.type == null)
+ createRange(g, link);
+ return link.rangeElement;
+ }
+
+ @Override
+ public Set<Domain> getDomain() {
+ return domain.keySet();
+ }
+
+ };
+
+ class RangeToDomain extends DomainToRange implements IBackwardMapping<Domain, Range> {
+
+ WriteGraph g;
+
+ public RangeToDomain(WriteGraph g) {
+ super(g);
+ this.g = g;
+ }
+ @Override
+ public Domain inverseGet(Range element) {
+
+ Link<Domain,Range> link = range.get(element);
+ if(link != null)
+ return link.domainElement;
+ return null;
+ }
+
+ @Override
+ public Domain inverseMap(WriteGraph graph, Range element)
+ throws MappingException {
+ Link<Domain,Range> link = range.get(element);
+ if(link == null) {
+ link = new Link<Domain,Range>(null, null, element);
+ link.rangeModified = true;
+ modifiedRangeLinks.add(link);
+ range.put(element, link);
+ createDomain(g, link);
+ }
+ else if(link.type == null)
+ createDomain(g, link);
+ return link.domainElement;
+ }
+
+
+ @Override
+ public Set<Range> getRange() {
+ return range.keySet();
+ }
+ };
+
+ @Override
+ public Set<Domain> getDomain() {
+ return domainSet;
+ }
+
+ @Override
+ public Set<Range> getRange() {
+ return rangeSet;
+ }
+
+
+ @Override
+ public synchronized Collection<Domain> updateDomain(WriteGraph g) throws MappingException {
+ LOGGER.info("Mapping.updateDomain");
+ RangeToDomain map = new RangeToDomain(g);
+ ArrayList<Domain> updated = new ArrayList<Domain>();
+ while(!modifiedRangeLinks.isEmpty()) {
+ LOGGER.info(" modifiedRangeLinks.size() = " + modifiedRangeLinks.size());
+
+ Link<Domain,Range> link = modifiedRangeLinks.remove(modifiedRangeLinks.size()-1);
+ link.rangeModified = false;
+ /*if(link.domainModified) {
+ link.domainModified = false;
+ modifiedDomainLinks.remove(link);
+ }*/
+
+ if(link.type == null) {
+ createDomain(g, link);
+ }
+
+ if(link.type.updateDomain(g, map, link.domainElement, link.rangeElement))
+ updated.add(link.domainElement);
+ }
+ if (listensDomain)
+ updateRange(g); //FIXME: without this listening would stop.
+ return updated;
+ }
+
+ @Override
+ public synchronized Collection<Range> updateRange(ReadGraph g) throws MappingException {
+ LOGGER.info("Mapping.updateRange");
+ DomainToRange map = new DomainToRange(g);
+ ArrayList<Range> updated = new ArrayList<Range>();
+ while(!modifiedDomainLinks.isEmpty()) {
+ LOGGER.info(" modifiedDomainLinks.size() = " + modifiedDomainLinks.size());
+
+ Link<Domain,Range> link = modifiedDomainLinks.remove(modifiedDomainLinks.size()-1);
+ link.domainModified = false;
+ /*if(link.rangeModified) {
+ link.rangeModified = false;
+ modifiedRangeLinks.remove(link);
+ }*/
+
+ if(link.type == null) {
+ createRange(g, link);
+ }
+
+ if(listensDomain) {
+ RangeUpdateRequest<Domain,Range> request = new RangeUpdateRequest<Domain,Range>(link, map, this);
+ try {
+ g.syncRequest(request, request);
+ } catch (DatabaseException e) {
+ throw new MappingException(e);
+ }
+ // TODO check if really modified
+ updated.add(link.rangeElement);
+ }
+ else
+ if(link.type.updateRange(g, map, link.domainElement, link.rangeElement))
+ updated.add(link.rangeElement);
+ }
+ return updated;
+ }
+
+ @Override
+ public Range get(Domain domainElement) {
+ Link<Domain,Range> link = domain.get(domainElement);
+ if(link == null)
+ return null;
+ return link.rangeElement;
+ }
+
+ @Override
+ public Domain inverseGet(Range rangeElement) {
+ Link<Domain,Range> link = range.get(rangeElement);
+ if(link == null)
+ return null;
+ return link.domainElement;
+ }
+
+ @Override
+ public Domain inverseMap(WriteGraph g, Range rangeElement) throws MappingException {
+ getRange().add(rangeElement);
+ updateDomain(g);
+ return inverseGet(rangeElement);
+ }
+
+ @Override
+ public Range map(ReadGraph g, Domain domainElement) throws MappingException {
+ getDomain().add(domainElement);
+ updateRange(g);
+ return get(domainElement);
+ }
+
+ void domainModified(Link<Domain,Range> link) {
+ if(!link.domainModified) {
+ synchronized(modifiedDomainLinks) {
+ LOGGER.info(" domainModified for " + link.rangeElement);
+ link.domainModified = true;
+ modifiedDomainLinks.add(link);
+ if(modifiedDomainLinks.size() == 1) {
+ for(IMappingListener listener : listeners)
+ listener.domainModified();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void domainModified(Domain domainElement) {
+ Link<Domain,Range> link = domain.get(domainElement);
+ if(link != null)
+ domainModified(link);
+ }
+
+ void rangeModified(Link<Domain,Range> link) {
+ if(!link.rangeModified) {
+ synchronized(modifiedRangeLinks) {
+ link.rangeModified = true;
+ modifiedRangeLinks.add(link);
+ if(modifiedRangeLinks.size() == 1) {
+ for(IMappingListener listener : listeners)
+ listener.rangeModified();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void rangeModified(Range rangeElement) {
+ Link<Domain,Range> link = range.get(rangeElement);
+ if(link != null)
+ rangeModified(link);
+ }
+
+ @Override
+ public boolean isDomainModified() {
+ return !modifiedDomainLinks.isEmpty();
+ }
+
+ @Override
+ public boolean isRangeModified() {
+ return !modifiedRangeLinks.isEmpty();
+ }
+
+ @Override
+ public Collection<Domain> getDomainModified() {
+ List<Domain> list = new ArrayList<Domain>(modifiedDomainLinks.size());
+ for (Link<Domain, Range> link : modifiedDomainLinks)
+ list.add(link.domainElement);
+ return list;
+
+ }
+
+ @Override
+ public Collection<Range> getRangeModified() {
+ List<Range> list = new ArrayList<Range>(modifiedRangeLinks.size());
+ for (Link<Domain, Range> link : modifiedRangeLinks)
+ list.add(link.rangeElement);
+ return list;
+ }
+
+ @Override
+ public void addMappingListener(IMappingListener listener) {
+ listeners.add(listener);
+ }
+
+ @Override
+ public void removeMappingListener(IMappingListener listener) {
+ listeners.remove(listener);
+ }
+
+ @Override
+ public Collection<Domain> getConflictingDomainElements() {
+ ArrayList<Domain> result = new ArrayList<Domain>();
+ if(modifiedDomainLinks.size() < modifiedRangeLinks.size()) {
+ for(Link<Domain,Range> link : modifiedDomainLinks)
+ if(link.rangeModified)
+ result.add(link.domainElement);
+ }
+ else {
+ for(Link<Domain,Range> link : modifiedRangeLinks)
+ if(link.domainModified)
+ result.add(link.domainElement);
+ }
+ return result;
+ }
+
+ @Override
+ public Collection<Range> getConflictingRangeElements() {
+ ArrayList<Range> result = new ArrayList<Range>();
+ if(modifiedDomainLinks.size() < modifiedRangeLinks.size()) {
+ for(Link<Domain,Range> link : modifiedDomainLinks)
+ if(link.rangeModified)
+ result.add(link.rangeElement);
+ }
+ else {
+ for(Link<Domain,Range> link : modifiedRangeLinks)
+ if(link.domainModified)
+ result.add(link.rangeElement);
+ }
+ return result;
+ }
+
+ @Override
+ public void dispose() {
+ disposed = true;
+ }
+
+ public boolean isDisposed() {
+ return disposed;
+ }
+
+}