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

org.bimserver.ifc.ReferenceCounter Maven / Gradle / Ivy

Go to download

Shared libraries, common parent for both BIMserver and BimServerClientLib

There is a newer version: 2.0.0
Show newest version
package org.bimserver.ifc;

/******************************************************************************
 * Copyright (C) 2009-2016  BIMserver.org
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see {@literal}.
 *****************************************************************************/

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.bimserver.emf.IdEObject;
import org.bimserver.emf.IfcModelInterface;
import org.eclipse.emf.common.util.AbstractEList;
import org.eclipse.emf.ecore.EReference;

public class ReferenceCounter {

	public static abstract class Reference {
		private final IdEObject idEObject;
		private final EReference eReference;
		private final IdEObject referredObject;

		public Reference(IdEObject idEObject, IdEObject referredObject, EReference eReference) {
			this.idEObject = idEObject;
			this.referredObject = referredObject;
			this.eReference = eReference;
		}

		public IdEObject getIdEObject() {
			return idEObject;
		}

		public EReference geteReference() {
			return eReference;
		}

		public abstract Reference reAttach(IdEObject mainObject);

		public IdEObject getReferredObject() {
			return referredObject;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((eReference == null) ? 0 : eReference.hashCode());
			result = prime * result + ((idEObject == null) ? 0 : idEObject.hashCode());
			result = prime * result + ((referredObject == null) ? 0 : referredObject.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;
			Reference other = (Reference) obj;
			if (eReference == null) {
				if (other.eReference != null)
					return false;
			} else if (!eReference.equals(other.eReference))
				return false;
			if (idEObject == null) {
				if (other.idEObject != null)
					return false;
			} else if (!idEObject.equals(other.idEObject))
				return false;
			if (referredObject == null) {
				if (other.referredObject != null)
					return false;
			} else if (!referredObject.equals(other.referredObject))
				return false;
			return true;
		}
	}

	public static class SingleReference extends Reference {

		public SingleReference(IdEObject idEObject, IdEObject referredObject, EReference eReference) {
			super(idEObject, referredObject, eReference);
		}

		@Override
		public Reference reAttach(IdEObject mainObject) {
//			System.out.println("Re-attaching S " + getReferredObject() + " to " + mainObject + " on " + getIdEObject() + "." + geteReference().getName());
			getIdEObject().eSet(geteReference(), mainObject);
			return new SingleReference(getIdEObject(), mainObject, geteReference());
		}
	}

	public static class MultiReference extends Reference {

		public MultiReference(IdEObject idEObject, IdEObject referredObject, EReference eReference) {
			super(idEObject, referredObject, eReference);
		}

		@SuppressWarnings({ "rawtypes", "unchecked" })
		@Override
		public Reference reAttach(IdEObject mainObject) {
//			System.out.println("Re-attaching M " + getReferredObject() + " to " + mainObject + " on " + getIdEObject() + "." + geteReference().getName());
			AbstractEList list = (AbstractEList) getIdEObject().eGet(geteReference());
			int index = list.indexOf(getReferredObject());
			if (index != -1) {
				if (!list.contains(mainObject)) {
					list.set(index, mainObject);
				}
			}

			// TODO if the old object really does exist multiple times, the new object should also exist multiple times... but it's probably a bug that it's there multiple times in the first place...
			while (list.contains(getReferredObject())) {
				list.remove(getReferredObject());
			}
			return new MultiReference(getIdEObject(), mainObject, geteReference());
		}
	}

	private final Map> references = new HashMap>();
	private final IfcModelInterface ifcModel;

	public ReferenceCounter(IfcModelInterface ifcModel) {
		this.ifcModel = ifcModel;
	}

	@SuppressWarnings("rawtypes")
	public void updateReferences() {
		references.clear();
		for (IdEObject idEObject : ifcModel.getValues()) {
			for (EReference eReference : idEObject.eClass().getEAllReferences()) {
				if (eReference.isMany()) {
					List list = (List) idEObject.eGet(eReference);
					for (Object o : list) {
						if (!references.containsKey(o)) {
							references.put((IdEObject) o, new HashSet());
						}
						references.get(o).add(new MultiReference(idEObject, (IdEObject) o, eReference));
					}
				} else {
					Object o = idEObject.eGet(eReference);
					if (!references.containsKey(o)) {
						references.put((IdEObject) o, new HashSet());
					}
					references.get(o).add(new SingleReference(idEObject, (IdEObject) o, eReference));
				}
			}
		}
	}

	public void remove(IdEObject idEObject) {
		removeInternal(idEObject);
//		LOGGER.info("Removing " + idEObject + " (" + totalRemoved + ")");
	}

	@SuppressWarnings("rawtypes")
	public int removeInternal(IdEObject idEObject) {
		int totalRemoved = 1;
		for (EReference eReference : idEObject.eClass().getEAllReferences()) {
			if (eReference.isMany()) {
				List list = (List) idEObject.eGet(eReference);
				for (Object o : list) {
					IdEObject refObject = (IdEObject) o;
					references.get(refObject).remove(idEObject);
					if (references.get(refObject).size() == 0) {
						totalRemoved += removeInternal(refObject);
					}
				}
			} else {
				IdEObject refObject = (IdEObject) idEObject.eGet(eReference);
				if (references.containsKey(refObject)) {
					references.get(refObject).remove(idEObject);
					if (references.get(refObject).size() == 0) {
						totalRemoved += removeInternal(refObject);
					}
				}
			}
		}
		return totalRemoved;
	}

	public Set getReferencesTo(IdEObject objectToRemove) {
		return references.get(objectToRemove);
	}

	public void addReference(Reference reference) {
		if (references.containsKey(reference.getReferredObject()))
			references.get(reference.getReferredObject()).add(reference);
		else {
			Set rSet = new HashSet();
			rSet.add(reference);
			references.put(reference.getReferredObject(), rSet);
		}
		if (reference.geteReference().getEOpposite() != null) {
			if (reference.geteReference().getEOpposite().isMany()) {
				MultiReference backReference = new MultiReference(reference.getReferredObject(), reference.getIdEObject(), reference.geteReference().getEOpposite());
				if (references.containsKey(reference.getIdEObject()))
					references.get(reference.getIdEObject()).add(backReference);
				else {
					Set rSet = new HashSet();
					rSet.add(backReference);
					references.put(reference.getIdEObject(), rSet);
				}
			} else {
				SingleReference backReference = new SingleReference(reference.getReferredObject(), reference.getIdEObject(), reference.geteReference().getEOpposite());
				if (references.containsKey(reference.getIdEObject()))
					references.get(reference.getIdEObject()).add(backReference);
				else {
					Set rSet = new HashSet();
					rSet.add(backReference);
					references.put(reference.getIdEObject(), rSet);
				}
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy