All Downloads are FREE. Search and download functionalities are using the official Maven repository.

iot.jcypher.domain.mapping.DomainState Maven / Gradle / Ivy

Go to download

Provides seamlessly integrated Java access to graph databases (Neo4J) at different levels of abstraction.

There is a newer version: 4.2.0
Show newest version
/************************************************************************
 * Copyright (c) 2014-2015 IoT-Solutions e.U.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *  http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ************************************************************************/

package iot.jcypher.domain.mapping;

import iot.jcypher.domain.ResolutionDepth;
import iot.jcypher.domain.genericmodel.DomainObject;
import iot.jcypher.domain.mapping.surrogate.InnerClassSurrogate;
import iot.jcypher.domain.mapping.surrogate.SurrogateState;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class DomainState {

	private Map object2IdMap;
	private Map relation2IdMap;
	
	// in a domain there can only exist unambiguous mappings between objects and nodes
	private Map id2ObjectMap;
	private Map> object2RelationsMap;
	private Map> objectField2KeyedRelationsMap;
	private Map> multiRelationsMap;
	private SurrogateState surrogateState;
	
	public DomainState() {
		super();
		this.object2IdMap = new HashMap();
		this.relation2IdMap = new HashMap();
		this.id2ObjectMap = new HashMap();
		this.object2RelationsMap = new HashMap>();
		this.objectField2KeyedRelationsMap = new HashMap>();
		this.multiRelationsMap = new HashMap>();
		this.surrogateState = new SurrogateState();
	}
	
	public DomainState createCopy() {
		DomainState ret = new DomainState();
		Iterator> it_1 = this.object2IdMap.entrySet().iterator();
		while(it_1.hasNext()) {
			Entry entry = it_1.next();
			ret.object2IdMap.put(entry.getKey(), entry.getValue().createCopy());
		}
		
		Map copiedRels = new IdentityHashMap();
		
		Iterator> it_2 = this.relation2IdMap.entrySet().iterator();
		while(it_2.hasNext()) {
			Entry entry = it_2.next();
			ret.relation2IdMap.put(copyRelation(entry.getKey(), copiedRels), entry.getValue().createCopy());
		}
		Iterator> it_3 = this.id2ObjectMap.entrySet().iterator();
		while(it_3.hasNext()) {
			Entry entry = it_3.next();
			ret.id2ObjectMap.put(entry.getKey(), entry.getValue());
		}
		Iterator>> it_4 = this.object2RelationsMap.entrySet().iterator();
		while(it_4.hasNext()) {
			Entry> entry = it_4.next();
			ret.object2RelationsMap.put(entry.getKey(), copyRelationsList(entry.getValue(), copiedRels));
		}
		
		Map copiedSftks =
				new IdentityHashMap();
		Iterator>> it_5 = this.objectField2KeyedRelationsMap.entrySet().iterator();
		while(it_5.hasNext()) {
			Entry> entry = it_5.next();
			ret.objectField2KeyedRelationsMap.put(
					copySftks(entry.getKey(), copiedSftks),
					copyRelationsList(entry.getValue(), copiedRels));
		}
		
		Map copiedSfks =
				new IdentityHashMap();
		Iterator>> it_6 = this.multiRelationsMap.entrySet().iterator();
		while(it_6.hasNext()) {
			Entry> entry = it_6.next();
			ret.multiRelationsMap.put(copySfks(entry.getKey(), copiedSfks),
					copyRelationsList(entry.getValue(), copiedRels));
		}
		
		ret.surrogateState = this.surrogateState.createCopy(copiedRels, ret);
		
		return ret;
	}
	
	private SourceFieldKey copySfks(SourceFieldKey toCopy,
			Map copiedSfks) {
		SourceFieldKey ret = copiedSfks.get(toCopy);
		if (ret == null) {
			ret = new SourceFieldKey(toCopy.getSource(), toCopy.getFieldName());
			copiedSfks.put(toCopy, ret);
		}
		return ret;
	}
	
	private SourceField2TargetKey copySftks(SourceField2TargetKey toCopy,
			Map copiedSftks) {
		SourceField2TargetKey ret = copiedSftks.get(toCopy);
		if (ret == null) {
			SourceFieldKey sfk = toCopy.getSourceFieldKey();
			ret = new SourceField2TargetKey(sfk.getSource(), sfk.getFieldName(), toCopy.getTarget());
			copiedSftks.put(toCopy, ret);
		}
		return ret;
	}
	
	@SuppressWarnings("unchecked")
	private  T copyRelation(T toCopy, Map copiedRels) {
		T crel = (T) copiedRels.get(toCopy);
		if (crel == null) {
			crel = (T) toCopy.createCopy(this);
			copiedRels.put(toCopy, crel);
		}
		return crel;
	}
	
	private  List copyRelationsList(List toCopy,
			Map copiedRels) {
		List ret = null;
		if (toCopy != null) {
			ret = new ArrayList();
			for (T rel : toCopy) {
				ret.add(copyRelation(rel, copiedRels));
			}
		}
		return ret;
	}
	
	private void addTo_Object2IdMap(Object key, Long value, int version, ResolutionDepth resolutionDepth) {
		LoadInfo loadInfo = new LoadInfo();
		loadInfo.id = value;
		loadInfo.version = version;
		loadInfo.resolutionDepth = resolutionDepth;
		this.object2IdMap.put(key, loadInfo);
	}
	
	public ResolutionDepth getResolutionDepth(Object key) {
		LoadInfo loadInfo = this.object2IdMap.get(key);
		if (loadInfo != null)
			return loadInfo.resolutionDepth;
		return null;
	}
	
	public Long getIdFrom_Object2IdMap(Object key) {
		LoadInfo loadInfo = this.object2IdMap.get(key);
		if (loadInfo != null)
			return loadInfo.id;
		return null;
	}
	
	public LoadInfo getLoadInfoFrom_Object2IdMap(Object key) {
		return this.object2IdMap.get(key);
	}
	
	public void add_Id2Relation(IRelation relat, Long id, int version) {
		RelationLoadInfo rli = new RelationLoadInfo();
		rli.id = id;
		rli.version = version;
		add_Info2Relation(relat, rli);
	}
	
	public void add_Info2Relation(IRelation relat, RelationLoadInfo rli) {
		if (!relat.isDeferred()) {
			IRelation toPut = relat; 
			if (relat instanceof KeyedRelationToChange) {
				KeyedRelation oldOne = ((KeyedRelationToChange)relat).existingOne;
				this.relation2IdMap.remove(oldOne);
				SourceField2TargetKey key = new SourceField2TargetKey(oldOne.getStart(),
						oldOne.getType(), oldOne.getEnd());
				List rels = this.objectField2KeyedRelationsMap.get(key);
				if (rels != null) {
					rels.remove(oldOne);
				}
				SourceFieldKey fieldKey = key.getSourceFieldKey();
				rels = this.multiRelationsMap.get(fieldKey);
				if (rels != null) {
					rels.remove(oldOne);
				}
				KeyedRelation newOne = ((KeyedRelationToChange)relat).getNewOne();
				toPut = newOne;
			}
			this.relation2IdMap.put(toPut, rli);
			
			if (toPut instanceof KeyedRelation) {
				SourceField2TargetKey key = new SourceField2TargetKey(toPut.getStart(),
						toPut.getType(), toPut.getEnd());
				List rels = this.objectField2KeyedRelationsMap.get(key);
				if (rels == null) {
					rels = new ArrayList();
					this.objectField2KeyedRelationsMap.put(key, rels);
				}
				if (!rels.contains(toPut))
					rels.add((KeyedRelation) toPut);
				SourceFieldKey fieldKey = key.getSourceFieldKey();
				rels = this.multiRelationsMap.get(fieldKey);
				if (rels == null) {
					rels = new ArrayList();
					this.multiRelationsMap.put(fieldKey, rels);
				}
				if (!rels.contains(toPut))
					rels.add((KeyedRelation) toPut);
			} else {
				List rels = this.object2RelationsMap.get(toPut.getStart());
				if (rels == null) {
					rels = new ArrayList();
					this.object2RelationsMap.put(toPut.getStart(), rels);
				}
				if (!rels.contains(toPut))
					rels.add(toPut);
			}
		} else {
			relat.setDomainState(this);
			relat.setId(rli.id.longValue());
		}
	}
	
	public RelationLoadInfo getFrom_Relation2IdMap(IRelation relat) {
		IRelation key;
		if (relat instanceof KeyedRelationToChange)
			key = ((KeyedRelationToChange)relat).existingOne;
		else
			key = relat;
		return this.relation2IdMap.get(key);
	}
	
	public void addTo_Id2ObjectMap(Object obj, Long id) {
		this.id2ObjectMap.put(id, obj);
	}
	
	public void add_Id2Object(Object obj, Long id, int version, ResolutionDepth resolutionDepth) {
		this.addTo_Id2ObjectMap(obj, id);
		this.addTo_Object2IdMap(obj, id, version, resolutionDepth);
	}
	
	public void replace_Id2Object(Object old, Object obj, Long id) {
		this.addTo_Id2ObjectMap(obj, id);
		LoadInfo li = this.object2IdMap.remove(old);
		this.addTo_Object2IdMap(obj, id, li.version, li.resolutionDepth);
	}
	
	public boolean existsRelation(IRelation relat) {
		List rels = this.object2RelationsMap.get(relat.getStart());
		if (rels != null) {
			for (IRelation r : rels) {
				if (r.equals(relat))
					return true;
			}
		}
		return false;
	}
	
	public List getKeyedRelations(SourceField2TargetKey key) {
		return this.objectField2KeyedRelationsMap.get(key);
	}
	
	public List getKeyedRelations(SourceFieldKey key) {
		return this.multiRelationsMap.get(key);
	}
	
	public IRelation findRelation(Object start, String type) {
		List rels = this.object2RelationsMap.get(start);
		if (rels != null) {
			for (IRelation r : rels) {
				if (r.getType().equals(type))
					return r;
			}
		}
		return null;
	}
	
	public void removeRelation(IRelation relat) {
		if (relat instanceof KeyedRelation) {
			SourceField2TargetKey key = new SourceField2TargetKey(relat.getStart(),
					relat.getType(), relat.getEnd());
			List rels = this.objectField2KeyedRelationsMap.get(key);
			if (rels != null) {
				rels.remove(relat);
			}
			SourceFieldKey fieldKey = key.getSourceFieldKey();
			rels = this.multiRelationsMap.get(fieldKey);
			if (rels != null) {
				rels.remove(relat);
			}
		} else {
			List rels = this.object2RelationsMap.get(relat.getStart());
			if (rels != null) {
				rels.remove(relat);
			}
		}
		this.relation2IdMap.remove(relat);
	}
	
	public Object getFrom_Id2ObjectMap(Long id) {
		return this.id2ObjectMap.get(id);
	}
	
	public SurrogateState getSurrogateState() {
		return surrogateState;
	}

	/***********************************/
	public interface IRelation {
		public String getType();
		public Object getStart();
		public Object getEnd();
		public void setDomainState(DomainState domainState);
		public void setId(long id);
		public IRelation createCopy(DomainState ds);
		
		/**
		 * @return true if start and / or end is an InnerClassSurrogate
		 */
		public boolean isDeferred();
	}

	/***********************************/
	public static class Relation implements IRelation {
		private String type;
		private Object start;
		private Object end;
		private DomainState domainState;
		private long id;
		
		public Relation(String type, Object start, Object end) {
			super();
			this.type = type;
			Object strt = start;
			if (start instanceof InnerClassSurrogate) {
				Object ro = ((InnerClassSurrogate)start).getRealObject();
				if (ro == null)
					((InnerClassSurrogate)start).addRelationUpdate(new RelationUpdate(true));
				else
					strt = ro;
			}
			this.start = strt;
			Object nd = end;
			if (end instanceof InnerClassSurrogate) {
				Object ro = ((InnerClassSurrogate)end).getRealObject();
				if (ro == null)
					((InnerClassSurrogate)end).addRelationUpdate(new RelationUpdate(false));
				else
					nd = ro;
			}
			this.end = nd;
		}

		@Override
		public IRelation createCopy(DomainState ds) {
			Relation ret = new Relation(this.type,	this.start, this.end);
			ret.domainState = ds;
			ret.id = this.id;
			return ret;
		}

		@Override
		public String getType() {
			return type;
		}

		@Override
		public Object getStart() {
			return start;
		}

		@Override
		public Object getEnd() {
			return end;
		}

		@Override
		public boolean isDeferred() {
			return this.start instanceof InnerClassSurrogate ||
					this.end instanceof InnerClassSurrogate;
		}

		@Override
		public void setDomainState(DomainState domainState) {
			this.domainState = domainState;
		}

		@Override
		public void setId(long id) {
			this.id = id;
		}
		
		protected long getId() {
			return this.id;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((end == null) ? 0 : end.hashCode());
			result = prime * result + ((start == null) ? 0 : start.hashCode());
			result = prime * result + ((type == null) ? 0 : type.hashCode());
			return result;
		}
		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Relation other = (Relation) obj;
			if (end == null) {
				if (other.end != null)
					return false;
			} else if (!end.equals(other.end))
				return false;
			if (start == null) {
				if (other.start != null)
					return false;
			} else if (!start.equals(other.start))
				return false;
			if (type == null) {
				if (other.type != null)
					return false;
			} else if (!type.equals(other.type))
				return false;
			return true;
		}

		@Override
		public String toString() {
			return "Relation [type=" + type + ", start=" + start + ", end="
					+ end + "]";
		}
		
		/**********************************/
		public class RelationUpdate {
			
			private boolean start;
			
			private RelationUpdate(boolean start) {
				super();
				this.start = start;
			}

			public void updateWith(Object startOrEnd) {
				RelationLoadInfo rli = Relation.this.domainState.getFrom_Relation2IdMap(Relation.this);
				int v = rli != null ? rli.getVersion() : -1;
				if (this.start)
					Relation.this.start = startOrEnd;
				else
					Relation.this.end = startOrEnd;
				Relation.this.domainState.add_Id2Relation(Relation.this,
						Relation.this.id, v);
			}
		}
	}
	
	/***********************************/
	public static class KeyedRelation extends Relation {

		// must be of simple type so that it can be mapped to a property
		private Object key;
		// must be either null or
		// must be of simple type so that it can be mapped to a property
		private Object value;
		
		public KeyedRelation(String type, Object key, Object start, Object end) {
			super(type, start, end);
			this.key = key;
		}
		
		@Override
		public IRelation createCopy(DomainState ds) {
			KeyedRelation ret = new KeyedRelation(getType(), this.key, getStart(), getEnd());
			ret.setDomainState(ds);
			ret.setId(getId());
			return ret;
		}
		
		public Object getKey() {
			return this.key;
		}

		public Object getValue() {
			return value;
		}

		public void setValue(Object value) {
			this.value = value;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = super.hashCode();
			result = prime * result + ((key == null) ? 0 : key.hashCode());
			result = prime * result + ((value == null) ? 0 : value.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (!super.equals(obj))
				return false;
			KeyedRelation other = (KeyedRelation) obj;
			if (key == null) {
				if (other.key != null)
					return false;
			} else if (!key.equals(other.key))
				return false;
			if (value == null) {
				if (other.value != null)
					return false;
			} else if (!value.equals(other.value))
				return false;
			return true;
		}

		@Override
		public String toString() {
			return "KeyedRelation [key=" + key + ", getType()=" + getType()
					+ ", getStart()=" + getStart() + ", getEnd()=" + getEnd()
					+ "]";
		}
		
	}
	
	/***********************************/
	public static class KeyedRelationToChange implements IRelation {
		private KeyedRelation existingOne;
		private KeyedRelation newOne;
		
		public KeyedRelationToChange(KeyedRelation existingOne, KeyedRelation newOne) {
			super();
			this.existingOne = existingOne;
			this.newOne = newOne;
		}

		@Override
		public IRelation createCopy(DomainState ds) {
			KeyedRelationToChange ret = new KeyedRelationToChange(
					(KeyedRelation)this.existingOne.createCopy(ds),
					(KeyedRelation)this.newOne.createCopy(ds));
			return ret;
		}

		@Override
		public String getType() {
			return this.existingOne.getType();
		}

		@Override
		public Object getStart() {
			return this.existingOne.getStart();
		}

		@Override
		public Object getEnd() {
			return this.existingOne.getEnd();
		}

		@Override
		public boolean isDeferred() {
			return this.newOne.isDeferred() || this.existingOne.isDeferred();
		}

		@Override
		public void setDomainState(DomainState domainState) {
			if (this.newOne.isDeferred())
				this.newOne.setDomainState(domainState);
			if (this.existingOne.isDeferred())
				this.existingOne.setDomainState(domainState);
		}

		@Override
		public void setId(long id) {
			if (this.newOne.isDeferred())
				this.newOne.setId(id);
			if (this.existingOne.isDeferred())
				this.existingOne.setId(id);
		}
		
		public KeyedRelation getNewOne() {
			return this.newOne;
		}
	}
	
	/********************************/
	public static class SourceField2TargetKey {
		private Object source;
		private String fieldName;
		private Object target;
		
		public SourceField2TargetKey(Object src, String fieldName, Object target) {
			super();
			this.source = src;
			this.fieldName = fieldName;
			this.target = target;
		}
		
		public SourceField2TargetKey(SourceFieldKey sfk, Object target) {
			super();
			this.source = sfk.getSource();
			this.fieldName = sfk.getFieldName();
			this.target = target;
		}

		public Object getTarget() {
			return this.target;
		}

		public SourceFieldKey getSourceFieldKey() {
			return new SourceFieldKey(this.source, this.fieldName);
		}
		
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result
					+ ((fieldName == null) ? 0 : fieldName.hashCode());
			result = prime * result
					+ ((source == null) ? 0 : source.hashCode());
			result = prime * result
					+ ((target == null) ? 0 : target.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			SourceField2TargetKey other = (SourceField2TargetKey) obj;
			if (fieldName == null) {
				if (other.fieldName != null)
					return false;
			} else if (!fieldName.equals(other.fieldName))
				return false;
			if (source == null) {
				if (other.source != null)
					return false;
			} else if (!source.equals(other.source))
				return false;
			if (target == null) {
				if (other.target != null)
					return false;
			} else if (!target.equals(other.target))
				return false;
			return true;
		}
	}
	
	/********************************/
	public static class SourceFieldKey {
		private Object source;
		private String fieldName;
		
		public SourceFieldKey(Object src, String fieldName) {
			super();
			this.source = src;
			this.fieldName = fieldName;
		}

		public Object getSource() {
			return source;
		}

		public String getFieldName() {
			return fieldName;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result
					+ ((fieldName == null) ? 0 : fieldName.hashCode());
			result = prime * result
					+ ((source == null) ? 0 : source.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			SourceFieldKey other = (SourceFieldKey) obj;
			if (fieldName == null) {
				if (other.fieldName != null)
					return false;
			} else if (!fieldName.equals(other.fieldName))
				return false;
			if (source == null) {
				if (other.source != null)
					return false;
			} else if (!source.equals(other.source))
				return false;
			return true;
		}
		
	}
	
	/********************************/
	public static class RelationLoadInfo {
		private Long id;
		private int version;
		
		private RelationLoadInfo createCopy() {
			RelationLoadInfo ret = new RelationLoadInfo();
			ret.id = this.id;
			ret.version = this.version;
			return ret;
		}
		
		public Long getId() {
			return id;
		}
		public int getVersion() {
			return version;
		}
	}
	
	/********************************/
	public static class LoadInfo {
		private Long id;
		private int version;
		private ResolutionDepth resolutionDepth;
		private DomainObject domainObject;
		
		public LoadInfo() {
			super();
		}
		private LoadInfo createCopy() {
			LoadInfo ret = new LoadInfo();
			ret.id = this.id;
			ret.version = this.version;
			ret.resolutionDepth = this.resolutionDepth;
			ret.domainObject = this.domainObject;
			return ret;
		}
		public Long getId() {
			return id;
		}
		public int getVersion() {
			return version;
		}
		public ResolutionDepth getResolutionDepth() {
			return resolutionDepth;
		}
		public LoadInfo setResolutionDepth(ResolutionDepth resolutionDepth) {
			this.resolutionDepth = resolutionDepth;
			return this;
		}
		public void setVersion(int v) {
			this.version = v;
		}
		public DomainObject getDomainObject() {
			return domainObject;
		}
		public void setDomainObject(DomainObject domainObject) {
			this.domainObject = domainObject;
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy