X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.objmap2%2Fsrc%2Forg%2Fsimantics%2Fobjmap%2Fgraph%2Fimpl%2FMapping.java;h=4820dae016b44c358fe52206d876f25a66b42fe3;hp=ee1eb2e0b4bcdd48662a5a319d9d1e0d54f9d671;hb=d5db319fc2c400a8c76249e1ed7ffd9deb9f7609;hpb=969bd23cab98a79ca9101af33334000879fb60c5 diff --git a/bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/impl/Mapping.java b/bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/impl/Mapping.java index ee1eb2e0b..4820dae01 100644 --- a/bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/impl/Mapping.java +++ b/bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/impl/Mapping.java @@ -1,476 +1,474 @@ -/******************************************************************************* - * 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 implements IMapping { - - static Logger LOGGER = Logger.getLogger("org.simantics.objmap"); - - - IMappingSchema schema; - - THashMap> domain = new THashMap>(); - THashMap> range = new THashMap>(); - ArrayList listeners = new ArrayList(); - - ArrayList> modifiedDomainLinks = new ArrayList>(); - ArrayList> modifiedRangeLinks = new ArrayList>(); - - boolean disposed = false; - - boolean listensDomain; - - public Mapping(IMappingSchema schema, boolean listensDomain) { - this.schema = schema; - this.listensDomain = listensDomain; - } - - private void removeLink(Link link) { - if(link.domainModified) - modifiedDomainLinks.remove(link); - if(link.rangeModified) - modifiedRangeLinks.remove(link); - link.removed = true; - } - - private void createDomain(WriteGraph g, Link link) throws MappingException { - LOGGER.info(" createDomain for " + link.rangeElement); - ILinkType 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 link) throws MappingException { - ILinkType 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 domainSet = new AbstractSet() { - - public boolean add(Domain e) { - if(domain.containsKey(e)) - return false; - Link link = new Link(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 link = domain.remove(o); - if(link == null) - return false; - removeLink(link); - if(link.rangeElement != null) - range.remove(link.rangeElement); - return true; - } - - @Override - public Iterator iterator() { - // FIXME does not implement Iterator.remove correctly - return domain.keySet().iterator(); - } - - @Override - public int size() { - return domain.size(); - } - - }; - - Set rangeSet = new AbstractSet() { - - public boolean add(Range e) { - if(range.containsKey(e)) - return false; - Link link = new Link(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 link = range.remove(o); - if(link == null) - return false; - removeLink(link); - if(link.domainElement != null) - domain.remove(link.domainElement); - return true; - } - - @Override - public Iterator iterator() { - // FIXME does not implement Iterator.remove correctly - return range.keySet().iterator(); - } - - @Override - public int size() { - return range.size(); - } - - }; - - class DomainToRange implements IForwardMapping { - - ReadGraph g; - - public DomainToRange(ReadGraph g) { - this.g = g; - } - - @Override - public Range get(Domain element) { - Link link = domain.get(element); - if (link != null) - return link.rangeElement; - return null; - - } - - @Override - public Range map(ReadGraph graph, Domain element) - throws MappingException { - Link link = domain.get(element); - if(link == null) { - link = new Link(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 getDomain() { - return domain.keySet(); - } - - }; - - class RangeToDomain extends DomainToRange implements IBackwardMapping { - - WriteGraph g; - - public RangeToDomain(WriteGraph g) { - super(g); - this.g = g; - } - @Override - public Domain inverseGet(Range element) { - - Link link = range.get(element); - if(link != null) - return link.domainElement; - return null; - } - - @Override - public Domain inverseMap(WriteGraph graph, Range element) - throws MappingException { - Link link = range.get(element); - if(link == null) { - link = new Link(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 getRange() { - return range.keySet(); - } - }; - - @Override - public Set getDomain() { - return domainSet; - } - - @Override - public Set getRange() { - return rangeSet; - } - - - @Override - public synchronized Collection updateDomain(WriteGraph g) throws MappingException { - LOGGER.info("Mapping.updateDomain"); - RangeToDomain map = new RangeToDomain(g); - ArrayList updated = new ArrayList(); - while(!modifiedRangeLinks.isEmpty()) { - LOGGER.info(" modifiedRangeLinks.size() = " + modifiedRangeLinks.size()); - - Link 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 updateRange(ReadGraph g) throws MappingException { - LOGGER.info("Mapping.updateRange"); - DomainToRange map = new DomainToRange(g); - ArrayList updated = new ArrayList(); - while(!modifiedDomainLinks.isEmpty()) { - LOGGER.info(" modifiedDomainLinks.size() = " + modifiedDomainLinks.size()); - - Link 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 request = new RangeUpdateRequest(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 link = domain.get(domainElement); - if(link == null) - return null; - return link.rangeElement; - } - - @Override - public Domain inverseGet(Range rangeElement) { - Link 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 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 link = domain.get(domainElement); - if(link != null) - domainModified(link); - } - - void rangeModified(Link 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 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 getDomainModified() { - List list = new ArrayList(modifiedDomainLinks.size()); - for (Link link : modifiedDomainLinks) - list.add(link.domainElement); - return list; - - } - - @Override - public Collection getRangeModified() { - List list = new ArrayList(modifiedRangeLinks.size()); - for (Link 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 getConflictingDomainElements() { - ArrayList result = new ArrayList(); - if(modifiedDomainLinks.size() < modifiedRangeLinks.size()) { - for(Link link : modifiedDomainLinks) - if(link.rangeModified) - result.add(link.domainElement); - } - else { - for(Link link : modifiedRangeLinks) - if(link.domainModified) - result.add(link.domainElement); - } - return result; - } - - @Override - public Collection getConflictingRangeElements() { - ArrayList result = new ArrayList(); - if(modifiedDomainLinks.size() < modifiedRangeLinks.size()) { - for(Link link : modifiedDomainLinks) - if(link.rangeModified) - result.add(link.rangeElement); - } - else { - for(Link link : modifiedRangeLinks) - if(link.domainModified) - result.add(link.rangeElement); - } - return result; - } - - @Override - public void dispose() { - disposed = true; - } - - public boolean isDisposed() { - return disposed; - } - -} +/******************************************************************************* + * 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 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.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; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import gnu.trove.map.hash.THashMap; + +/** + * 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 implements IMapping { + + static final Logger LOGGER = LoggerFactory.getLogger(Mapping.class); + + + IMappingSchema schema; + + THashMap> domain = new THashMap>(); + THashMap> range = new THashMap>(); + ArrayList listeners = new ArrayList(); + + ArrayList> modifiedDomainLinks = new ArrayList>(); + ArrayList> modifiedRangeLinks = new ArrayList>(); + + boolean disposed = false; + + boolean listensDomain; + + public Mapping(IMappingSchema schema, boolean listensDomain) { + this.schema = schema; + this.listensDomain = listensDomain; + } + + private void removeLink(Link link) { + if(link.domainModified) + modifiedDomainLinks.remove(link); + if(link.rangeModified) + modifiedRangeLinks.remove(link); + link.removed = true; + } + + private void createDomain(WriteGraph g, Link link) throws MappingException { + LOGGER.trace(" createDomain for " + link.rangeElement); + ILinkType 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(), domainElement, link.rangeElement); + + // TODO Should we do this only if the mapping is listening? + domainModified(link); + } + + private void createRange(ReadGraph g, Link link) throws MappingException { + ILinkType 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(), link.domainElement, rangeElement); + } + + Set domainSet = new AbstractSet() { + + public boolean add(Domain e) { + if(domain.containsKey(e)) + return false; + Link link = new Link(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 link = domain.remove(o); + if(link == null) + return false; + removeLink(link); + if(link.rangeElement != null) + range.remove(link.rangeElement); + return true; + } + + @Override + public Iterator iterator() { + // FIXME does not implement Iterator.remove correctly + return domain.keySet().iterator(); + } + + @Override + public int size() { + return domain.size(); + } + + }; + + Set rangeSet = new AbstractSet() { + + public boolean add(Range e) { + if(range.containsKey(e)) + return false; + Link link = new Link(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 link = range.remove(o); + if(link == null) + return false; + removeLink(link); + if(link.domainElement != null) + domain.remove(link.domainElement); + return true; + } + + @Override + public Iterator iterator() { + // FIXME does not implement Iterator.remove correctly + return range.keySet().iterator(); + } + + @Override + public int size() { + return range.size(); + } + + }; + + class DomainToRange implements IForwardMapping { + + public DomainToRange() { + } + + @Override + public Range get(Domain element) { + Link link = domain.get(element); + if (link != null) + return link.rangeElement; + return null; + + } + + @Override + public Range map(ReadGraph graph, Domain element) + throws MappingException { + Link link = domain.get(element); + if(link == null) { + link = new Link(null, element, null); + link.domainModified = true; + modifiedDomainLinks.add(link); + domain.put(element, link); + createRange(graph, link); + } + else if(link.type == null) + createRange(graph, link); + return link.rangeElement; + } + + @Override + public Set getDomain() { + return domain.keySet(); + } + + }; + + class RangeToDomain extends DomainToRange implements IBackwardMapping { + + public RangeToDomain() { + super(); + } + + @Override + public Domain inverseGet(Range element) { + + Link link = range.get(element); + if(link != null) + return link.domainElement; + return null; + } + + @Override + public Domain inverseMap(WriteGraph graph, Range element) + throws MappingException { + Link link = range.get(element); + if(link == null) { + link = new Link(null, null, element); + link.rangeModified = true; + modifiedRangeLinks.add(link); + range.put(element, link); + createDomain(graph, link); + } + else if(link.type == null) + createDomain(graph, link); + return link.domainElement; + } + + + @Override + public Set getRange() { + return range.keySet(); + } + }; + + @Override + public Set getDomain() { + return domainSet; + } + + @Override + public Set getRange() { + return rangeSet; + } + + + @Override + public synchronized Collection updateDomain(WriteGraph g) throws MappingException { + LOGGER.trace("Mapping.updateDomain"); + RangeToDomain map = new RangeToDomain(); + ArrayList updated = new ArrayList(); + while(!modifiedRangeLinks.isEmpty()) { + LOGGER.trace(" modifiedRangeLinks.size() = " + modifiedRangeLinks.size()); + + Link 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); + } + else { + 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 updateRange(ReadGraph g) throws MappingException { + LOGGER.trace("Mapping.updateRange"); + DomainToRange map = new DomainToRange(); + ArrayList updated = new ArrayList(); + while(!modifiedDomainLinks.isEmpty()) { + LOGGER.trace(" modifiedDomainLinks.size() = " + modifiedDomainLinks.size()); + + Link 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 request = new RangeUpdateRequest(link, map, this); + boolean changes; + try { + changes = g.syncRequest(request, request) > 0; + } catch (DatabaseException e) { + throw new MappingException(e); + } + + if (changes) + 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 link = domain.get(domainElement); + if(link == null) + return null; + return link.rangeElement; + } + + @Override + public Domain inverseGet(Range rangeElement) { + Link 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 link) { + if(!link.domainModified) { + synchronized(modifiedDomainLinks) { + LOGGER.trace(" 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 link = domain.get(domainElement); + if(link != null) + domainModified(link); + } + + void rangeModified(Link 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 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 getDomainModified() { + List list = new ArrayList(modifiedDomainLinks.size()); + for (Link link : modifiedDomainLinks) + list.add(link.domainElement); + return list; + + } + + @Override + public Collection getRangeModified() { + List list = new ArrayList(modifiedRangeLinks.size()); + for (Link 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 getConflictingDomainElements() { + ArrayList result = new ArrayList(); + if(modifiedDomainLinks.size() < modifiedRangeLinks.size()) { + for(Link link : modifiedDomainLinks) + if(link.rangeModified) + result.add(link.domainElement); + } + else { + for(Link link : modifiedRangeLinks) + if(link.domainModified) + result.add(link.domainElement); + } + return result; + } + + @Override + public Collection getConflictingRangeElements() { + ArrayList result = new ArrayList(); + if(modifiedDomainLinks.size() < modifiedRangeLinks.size()) { + for(Link link : modifiedDomainLinks) + if(link.rangeModified) + result.add(link.rangeElement); + } + else { + for(Link link : modifiedRangeLinks) + if(link.domainModified) + result.add(link.rangeElement); + } + return result; + } + + @Override + public void dispose() { + disposed = true; + } + + public boolean isDisposed() { + return disposed; + } + +}