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

org.bimserver.database.migrations.Schema Maven / Gradle / Ivy

package org.bimserver.database.migrations;

/******************************************************************************
 * 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.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import org.bimserver.database.BimserverLockConflictException;
import org.bimserver.database.Database;
import org.bimserver.database.DatabaseSession;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Schema {
	private static final Logger LOGGER = LoggerFactory.getLogger(Schema.class);
	private final Map packages = new TreeMap();
	private final Map> directSubClasses = new HashMap>();
	private final Map> indirectSubClasses = new HashMap>();
	
	private final Set changes = new LinkedHashSet();
	
	public static enum Multiplicity {
		SINGLE,
		MANY
	}

	private void initSubClasses() {
		for (EPackage ePackage : packages.values()) {
			for (EClassifier eClassifier : ePackage.getEClassifiers()) {
				if (eClassifier instanceof EClass) {
					EClass eClass = (EClass) eClassifier;
					initDirectSubClasses(eClass);
					initIndirectSubClasses(eClass);
				}
			}
		}
	}

	private void initDirectSubClasses(EClass eClass) {
		HashSet set = new HashSet();
		directSubClasses.put(eClass, set);
		set.add(eClass);
		for (EClassifier eClassifier : eClass.getEPackage().getEClassifiers()) {
			if (eClassifier instanceof EClass) {
				EClass e = (EClass) eClassifier;
				if (e.getESuperTypes().contains(eClass)) {
					set.add(e);
				}
			}
		}
	}

	public Set getEPackages() {
		return new HashSet(packages.values());
	}
	
	private void initIndirectSubClasses(EClass eClass) {
		HashSet set = new HashSet();
		indirectSubClasses.put(eClass, set);
		set.add(eClass);
		for (EClassifier eClassifier : eClass.getEPackage().getEClassifiers()) {
			if (eClassifier instanceof EClass) {
				EClass e = (EClass) eClassifier;
				if (eClass.isSuperTypeOf(e)) {
					set.add(e);
				}
			}
		}
	}
	
	public EPackage getEPackage(String name) {
		return packages.get(name);
	}
	
	public EPackage createEPackage(String name) {
		EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
		ePackage.setName(name);
		ePackage.setNsPrefix(name);
		ePackage.setNsURI(name);
		packages.put(ePackage.getName(), ePackage);
		return ePackage;
	}
	
	public EEnum createEEnum(EPackage ePackage, String name) {
		EEnum eEnum = EcoreFactory.eINSTANCE.createEEnum();
		changes.add(new NewEnumChange(eEnum));
		ePackage.getEClassifiers().add(eEnum);
		eEnum.setName(name);
		return eEnum;
	}
	
	public EEnumLiteral createEEnumLiteral(EEnum eEnum, String name, int value) {
		EEnumLiteral eEnumLiteral = EcoreFactory.eINSTANCE.createEEnumLiteral();
		eEnumLiteral.setValue(value);
		eEnum.getELiterals().add(eEnumLiteral);
		eEnumLiteral.setName(name);
		return eEnumLiteral;
	}

	public EEnumLiteral createEEnumLiteral(EEnum eEnum, String name) {
		EEnumLiteral eEnumLiteral = EcoreFactory.eINSTANCE.createEEnumLiteral();
		if (eEnum.getELiterals().size() == 0) {
			eEnumLiteral.setValue(0);
		} else {
			int largestValue = Integer.MIN_VALUE;
			for (EEnumLiteral existingLiteral : eEnum.getELiterals()) {
				if (existingLiteral.getValue() > largestValue) {
					largestValue = existingLiteral.getValue();
				}
			}
			eEnumLiteral.setValue(largestValue + 1);
		}
		eEnum.getELiterals().add(eEnumLiteral);
		eEnumLiteral.setName(name);
		return eEnumLiteral;
	}

	public EClass createEClass(EPackage ePackage, String name, EClass... superClasses) {
		EClass eClass = EcoreFactory.eINSTANCE.createEClass();
		eClass.setName(name);
		changes.add(new NewClassChange(eClass));
		for (EClass superClass : superClasses) {
			eClass.getESuperTypes().add(superClass);
		}
		ePackage.getEClassifiers().add(eClass);
		return eClass;
	}

	public EAttribute createEAttribute(EClass eClass, String name, EDataType eDataType, Multiplicity multiplicity) {
		EAttribute eAttribute = EcoreFactory.eINSTANCE.createEAttribute();
		eAttribute.setName(name);
		if (multiplicity == Multiplicity.MANY) {
			eAttribute.setUpperBound(-1);
		}
		if (!isNew(eClass)) {
			changes.add(new NewAttributeChange(this, eClass.getEAllStructuralFeatures().size(), eAttribute));
		}
		eAttribute.setEType(eDataType);
		eClass.getEStructuralFeatures().add(eAttribute);
		return eAttribute;
	}

	public EAttribute createEAttribute(EClass eClass, String name, EDataType eDataType) {
		return createEAttribute(eClass, name, eDataType, Multiplicity.SINGLE);
	}
	
	private boolean isNew(EClass eClass) {
		for (Change change : changes) {
			if (change instanceof NewClassChange) {
				NewClassChange newClassChange = (NewClassChange)change;
				if (newClassChange.getEClass() == eClass) {
					return true;
				}
			}
		}
		return false;
	}

	public EReference createEReference(EClass eClass, String name, EClass type, Multiplicity multiplicity) {
		EReference eReference = EcoreFactory.eINSTANCE.createEReference();
		eReference.setName(name);
		if (multiplicity == Multiplicity.MANY) {
			eReference.setUpperBound(-1);
		}
		if (!isNew(eClass)) {
			changes.add(new NewReferenceChange(this, eClass.getEAllStructuralFeatures().size(), eReference));
		}
		eReference.setEType(type);
		eClass.getEStructuralFeatures().add(eReference);
		return eReference;
	}
	
	public void writeToEcore(File file) {
        ResourceSet resourceSet = new ResourceSetImpl();
        resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("ecore", new EcoreResourceFactoryImpl());
        Resource resource = resourceSet.createResource(URI.createFileURI(file.getAbsolutePath()));
        for (EPackage ePackage : packages.values()) {
            resource.getContents().add(ePackage);
        }
        try {
            resource.save(null);
        } catch (IOException e) {
			LOGGER.error("", e);
        }
	}

	public void upgradeDatabase(Database database, int version, DatabaseSession databaseSession) {
		LOGGER.info("Upgrading database to version " + version);
		initSubClasses();
		for (Change change : changes) {
			try {
				change.change(database, databaseSession);
			} catch (Exception e) {
				LOGGER.error("", e);
			}
		}
		try {
			database.setDatabaseVersion(version, databaseSession);
		} catch (BimserverLockConflictException e) {
			LOGGER.error("", e);
		}
	}

	public EClass getEClass(String packageName, String name) {
		EPackage ePackage = packages.get(packageName);
		if (ePackage == null) {
			throw new RuntimeException("Package with name " + name + " not found");
		}
		EClass eClassifier = (EClass) ePackage.getEClassifier(name);
		if (eClassifier == null) {
			throw new RuntimeException("Class " + name + " not found in " + packageName);
		}
		return eClassifier;
	}

	public void clearUpdates() {
		changes.clear();
	}

	@SuppressWarnings("rawtypes")
	public void loadEcore(String name, InputStream inputStream) {
        ResourceSet resourceSet = new ResourceSetImpl();
        resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("ecore", new EcoreResourceFactoryImpl());
        Resource resource = resourceSet.createResource(URI.createURI(name));
        try {
			resource.load(inputStream, new HashMap());
			for (EObject eObject : resource.getContents()) {
				if (eObject instanceof EPackage) {
					EPackage ePackage = (EPackage)eObject;
					addEPackage(ePackage);
				}
			}
		} catch (IOException e) {
			LOGGER.error("", e);
		}
	}

	public void addEPackage(EPackage ePackage) {
		packages.put(ePackage.getName(), ePackage);
		changes.add(new NewPackageChange(ePackage));
		for (EClassifier eClassifier : ePackage.getEClassifiers()) {
			if (eClassifier instanceof EClass) {
				EClass eClass = (EClass)eClassifier;
				addEClass(eClass);
			}
		}
	}

	private void addEClass(EClass eClass) {
		changes.add(new NewClassChange(eClass));
	}

	public Set getSubClasses(EClass eClass) {
		return indirectSubClasses.get(eClass);
	}

	public EEnum getEEnum(String packageName, String enumName) {
		return (EEnum) packages.get(packageName).getEClassifier(enumName);
	}

	public EDataType createEDataType(EPackage ePackage, EDataType dataType) {
		ePackage.getEClassifiers().add(dataType);
		return dataType;
	}

	public EClass createEClass(String packageName, String className) {
		return createEClass(getEPackage(packageName), className);
	}

	public EEnum createEEnum(String packageName, String enumName) {
		return createEEnum(getEPackage(packageName), enumName);
	}

	public EClass createEClass(String packageName, String className, EClass... superTypes) {
		return createEClass(getEPackage(packageName), className, superTypes);
	}

	public void removeEReference(EClass eClass, String name) {
		eClass.getEStructuralFeatures().remove(eClass.getEStructuralFeature(name));
	}

	public void addIndex(EStructuralFeature eStructuralFeature) {
		changes.add(new AddIndexChange(this, eStructuralFeature));
		EAnnotation index = EcoreFactory.eINSTANCE.createEAnnotation();
		index.setSource("singleindex");

		eStructuralFeature.getEAnnotations().add(index);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy