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

org.fuchss.objectcasket.objectpacker.impl.SessionImpl Maven / Gradle / Ivy

Go to download

Object Casket is a simple O/R mapper that can be used together with the Java Persistence API (JPA). The aim is to provide a simple solution for small projects to store multi-related entities in a simple manner.

There is a newer version: 0.20.17
Show newest version
package org.fuchss.objectcasket.objectpacker.impl;

import java.io.Serializable;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Set;

import jakarta.persistence.Table;

import org.fuchss.objectcasket.common.CasketError.CE1;
import org.fuchss.objectcasket.common.CasketException;
import org.fuchss.objectcasket.common.IntolerantHashMap;
import org.fuchss.objectcasket.common.IntolerantMap;
import org.fuchss.objectcasket.common.Util;
import org.fuchss.objectcasket.objectpacker.port.Session;
import org.fuchss.objectcasket.tablemodule.port.TableModule;
import org.fuchss.objectcasket.tablemodule.port.TableModuleFactory;

class SessionImpl extends SyncedSession implements Session {

	protected IntolerantMap, ClassInfo> classInfoMap = new IntolerantHashMap<>();
	protected IntolerantMap, String> classTableNameMap = new IntolerantHashMap<>();
	private final IntolerantMap> tableNameClassMap = new IntolerantHashMap<>();

	protected IntolerantMap, JoinTableBuilder> joinTabFactoryFactoryMap = new IntolerantHashMap<>();

	protected boolean check; // enables checking for reserved symbols
	protected Boolean assignOnly; // true = assignOnly, false = createOnly, null = assign or create

	private SessionImpl(TableModule tabMod, ConfigurationImpl config) {
		super(tabMod, config);
	}

	static SessionImpl editDomainBuilder(TableModuleFactory modFac, ConfigurationImpl config) throws CasketException {
		SessionImpl session = new SessionImpl(modFac.newTableModule(config.getConfig()), config);
		session.assignOnly = true;
		session.init(modFac);
		session.assignOnly = null;
		return session;
	}

	static SessionImpl mkDomainBuilder(TableModuleFactory modFac, ConfigurationImpl config) throws CasketException {
		SessionImpl session = new SessionImpl(modFac.newTableModule(config.getConfig()), config);
		session.assignOnly = false;
		session.init(modFac);
		return session;
	}

	static SessionImpl createSession(TableModuleFactory modFac, ConfigurationImpl config) throws CasketException {
		SessionImpl session = new SessionImpl(modFac.newTableModule(config.getConfig()), config);
		session.assignOnly = true;
		session.init(modFac);
		return session;
	}

	private void init(TableModuleFactory modFac) throws CasketException {
		try {
			this.declareClass(M2OInfo.class);
			this.declareClass(M2MInfo.class);
			this.check = true;
		} catch (Exception exc) {
			modFac.closeModule(this.tableModule);
			throw CasketException.build(exc);
		}

	}

	@Override
	public synchronized void declareClass(Class... clazz) throws CasketException {
		Set> processedClasses = new HashSet<>();
		Set> processedM2MInfo = new HashSet<>();
		if (this.transaction != null)
			throw CE1.TRANSACTION_RUNNING.defaultBuild(this.transaction);
		try {
			for (Class singleClass : clazz)
				this.forwardDeclareClass(singleClass, processedClasses);
			for (Class singleClass : clazz) {
				ObjectBuilder builder = new ObjectBuilder<>(this, this.tableModule, this.classInfoMap.getIfExists(singleClass));
				this.objectFactoryMap.putIfNew(singleClass, builder);
				for (M2MInfo info : builder.m2mFieldInfoMap.values()) {
					processedM2MInfo.add(info);
					this.joinTabFactoryFactoryMap.putIfNew(info, new JoinTableBuilder<>(this, this.tableModule, info));
				}
			}
		} catch (Exception exc) {
			this.undoDeclare(processedClasses, processedM2MInfo);
			throw CasketException.build(exc);
		}
	}

	private void undoDeclare(Set> processedClasses, Set> processedM2MInfo) {
		for (Class singleClass : processedClasses) {
			this.classInfoMap.remove(singleClass);
			String tableName = this.classTableNameMap.remove(singleClass);
			this.tableNameClassMap.remove(tableName);
			this.objectFactoryMap.remove(singleClass);
		}
		for (M2MInfo info : processedM2MInfo)
			this.joinTabFactoryFactoryMap.remove(info);
	}

	private void forwardDeclareClass(Class clazz, Set> processedClasses) throws CasketException {
		Util.objectsNotNull(clazz);
		String tableName = this.checkClassAndGetTableName(clazz);
		ClassInfo info = new ClassInfo<>(clazz, tableName);
		this.classTableNameMap.put(clazz, tableName);
		this.tableNameClassMap.put(tableName, clazz);
		processedClasses.add(clazz);
		this.classInfoMap.put(clazz, info);
	}

	private String checkClassAndGetTableName(Class clazz) throws CasketException {
		String tableName = this.computeTableName(clazz);
		if (Boolean.TRUE.equals(this.assignOnly) && !this.tableModule.tableExists(tableName))
			throw CE1.MISSING_TABLE.defaultBuild(tableName);
		if (Boolean.FALSE.equals(this.assignOnly) && this.tableModule.tableExists(tableName))
			throw CE1.CLASS_ALREADY_DECLARED.defaultBuild(clazz);
		if (this.classInfoMap.containsKey(clazz) || this.tableNameClassMap.containsKey(tableName))
			throw CE1.CLASS_ALREADY_DECLARED.defaultBuild(clazz);
		return tableName;
	}

	private String computeTableName(Class clazz) throws CasketException {
		if (!Modifier.isFinal(clazz.getModifiers()))
			throw CE1.NON_FINAL_CLASS.defaultBuild(clazz);
		if (clazz.getAnnotation(jakarta.persistence.Entity.class) == null)
			throw CE1.MISSING_ENTITY_ANNOTATION.defaultBuild(clazz);

		Table table = clazz.getAnnotation(Table.class);
		String tableName = (table != null) ? table.name() : "";
		tableName = tableName.isEmpty() ? clazz.getSimpleName() : tableName;

		if (this.check && tableName.contains("@"))
			throw CE1.INVALID_NAME.defaultBuild(tableName);

		return tableName;
	}

	 boolean isManaged(T obj) throws CasketException {
		Util.objectsNotNull(obj);
		@SuppressWarnings("unchecked")
		ObjectBuilder objFactory = (ObjectBuilder) this.objectFactoryMap.getIfExists(obj.getClass());
		return objFactory.objectRowMap.containsKey(obj);
	}

	 void addClient(T supplier) throws CasketException {
		Util.objectsNotNull(supplier);
		@SuppressWarnings("unchecked")
		ObjectBuilder objFac = (ObjectBuilder) this.objectFactoryMap.getIfExists(supplier.getClass());
		objFac.addClient(supplier, this.transaction);
	}

	 void removeClient(Class clazz, Serializable pk) throws CasketException {
		Util.objectsNotNull(clazz);
		if (pk == null)
			return;
		@SuppressWarnings("unchecked")
		ObjectBuilder objFac = (ObjectBuilder) this.objectFactoryMap.getIfExists(clazz);
		objFac.removeClient(pk, this.transaction);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy