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

org.revenj.LocatorDataContext Maven / Gradle / Ivy

The newest version!
package org.revenj;

import org.revenj.extensibility.Container;
import org.revenj.patterns.*;
import org.revenj.patterns.DataSource;
import rx.Observable;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

final class LocatorDataContext implements UnitOfWork {
	private final Container scope;
	private ConcurrentHashMap, SearchableRepository> searchRepositories;
	private ConcurrentHashMap, Repository> lookupRepositories;
	private ConcurrentHashMap, PersistableRepository> persistableRepositories;
	private ConcurrentHashMap, Repository> historyRepositories;
	private ConcurrentHashMap, DomainEventStore> eventStores;
	private GlobalEventStore globalEventStore;
	private DataChangeNotification changes;
	private final boolean manageConnection;
	private final Connection connection;
	private boolean hasChanges;
	private boolean closed;

	LocatorDataContext(Container scope, boolean manageConnection, Connection connection) {
		this.scope = scope;
		this.manageConnection = manageConnection;
		this.connection = connection;
	}

	static DataContext asDataContext(Container container) {
		return new LocatorDataContext(container, false, null);
	}

	static DataContext asDataContext(Container container, Connection connection) {
		Container scope = container.createScope();
		scope.registerInstance(Connection.class, connection, false);
		return new LocatorDataContext(scope, false, connection);
	}

	static UnitOfWork asUnitOfWork(Container container) {
		javax.sql.DataSource dataSource = container.resolve(javax.sql.DataSource.class);
		java.sql.Connection connection = null;
		try {
			connection = dataSource.getConnection();
			connection.setAutoCommit(false);
		} catch (SQLException e) {
			try {
				if (connection != null) connection.close();
			} catch (SQLException ignore) {
			}
			try {
				connection = dataSource.getConnection();
				connection.setAutoCommit(false);
			} catch (SQLException ex) {
				throw new RuntimeException(ex);
			}
		}
		Container scope = container.createScope();
		scope.registerInstance(Connection.class, connection, false);
		return new LocatorDataContext(scope, true, connection);
	}

	private  SearchableRepository getSearchableRepository(Class manifest) {
		if (closed) throw new RuntimeException("Unit of work has been closed");
		if (searchRepositories == null) searchRepositories = new ConcurrentHashMap<>();
		return searchRepositories.computeIfAbsent(manifest, clazz ->
		{
			if (persistableRepositories != null) {
				PersistableRepository repository = persistableRepositories.get(manifest);
				if (repository != null) return repository;
			}
			try {
				return (SearchableRepository) scope.resolve(Utils.makeGenericType(SearchableRepository.class, manifest));
			} catch (ReflectiveOperationException ex) {
				throw new RuntimeException("Repository is not registered for: " + manifest, ex);
			}
		});
	}

	private Repository getLookupRepository(Class manifest) {
		if (closed) throw new RuntimeException("Unit of work has been closed");
		if (lookupRepositories == null) lookupRepositories = new ConcurrentHashMap<>();
		return lookupRepositories.computeIfAbsent(manifest, clazz ->
		{
			if (persistableRepositories != null) {
				PersistableRepository repository = persistableRepositories.get(manifest);
				if (repository != null) return repository;
			}
			try {
				return (Repository) scope.resolve(Utils.makeGenericType(Repository.class, manifest));
			} catch (ReflectiveOperationException ex) {
				throw new RuntimeException("Repository is not registered for: " + manifest, ex);
			}
		});
	}

	private Repository getHistoryRepository(Class manifest) {
		if (closed) throw new RuntimeException("Unit of work has been closed");
		if (historyRepositories == null) historyRepositories = new ConcurrentHashMap<>();
		return historyRepositories.computeIfAbsent(manifest, clazz ->
		{
			try {
				return (Repository) scope.resolve(Utils.makeGenericType(Repository.class, Utils.makeGenericType(History.class, manifest)));
			} catch (ReflectiveOperationException ex) {
				throw new RuntimeException("Repository is not registered for: " + manifest, ex);
			}
		});
	}

	private PersistableRepository getPersistableRepository(Class manifest) {
		if (closed) throw new RuntimeException("Unit of work has been closed");
		if (persistableRepositories == null) persistableRepositories = new ConcurrentHashMap<>();
		return persistableRepositories.computeIfAbsent(manifest, clazz ->
		{
			try {
				return (PersistableRepository) scope.resolve(Utils.makeGenericType(PersistableRepository.class, manifest));
			} catch (ReflectiveOperationException ex) {
				throw new RuntimeException("Repository is not registered for: " + manifest, ex);
			}
		});
	}

	private DomainEventStore getEventStore(Class manifest) {
		if (closed) throw new RuntimeException("Unit of work has been closed");
		if (eventStores == null) eventStores = new ConcurrentHashMap<>();
		return eventStores.computeIfAbsent(manifest, clazz ->
		{
			try {
				return (DomainEventStore) scope.resolve(Utils.makeGenericType(SearchableRepository.class, manifest));
			} catch (ReflectiveOperationException ex) {
				throw new RuntimeException("Domain event store is not registered for: " + manifest, ex);
			}
		});
	}

	@Override
	public  Optional find(Class manifest, String uri) {
		return getLookupRepository(manifest).find(uri);
	}

	@Override
	public  List find(Class manifest, Collection uris) {
		return getLookupRepository(manifest).find(uris);
	}

	@Override
	public  Query query(Class manifest, Specification filter) {
		return getSearchableRepository(manifest).query(filter);
	}

	@Override
	public  List search(Class manifest, Specification filter, Integer limit, Integer offset) {
		return getSearchableRepository(manifest).search(filter, limit, offset);
	}

	@Override
	public  long count(Class manifest, Specification filter) {
		return getSearchableRepository(manifest).count(filter);
	}

	@Override
	public  boolean exists(Class manifest, Specification filter) {
		return getSearchableRepository(manifest).exists(filter);
	}

	@Override
	public  void create(Collection aggregates) throws IOException {
		if (aggregates.size() == 0) {
			return;
		}
		Class manifest = aggregates.iterator().next().getClass();
		getPersistableRepository(manifest).insert(aggregates);
		hasChanges = true;
	}

	@Override
	public  void updatePairs(Collection> pairs) throws IOException {
		if (pairs.size() == 0) {
			return;
		}
		Class manifest = pairs.iterator().next().getValue().getClass();
		getPersistableRepository(manifest).persist(null, pairs, null);
		hasChanges = true;
	}

	@Override
	public  void delete(Collection aggregates) throws IOException {
		if (aggregates.size() == 0) {
			return;
		}
		Class manifest = aggregates.iterator().next().getClass();
		getPersistableRepository(manifest).delete(aggregates);
		hasChanges = true;
	}

	@Override
	public  void submit(Collection events) {
		if (events.size() == 0) {
			return;
		}
		Class manifest = events.iterator().next().getClass();
		getEventStore(manifest).submit(events);
		hasChanges = true;
	}

	@Override
	public  void queue(Collection events) {
		if (globalEventStore == null) {
			globalEventStore = scope.resolve(GlobalEventStore.class);
		}
		for (T e : events) {
			globalEventStore.queue(e);
		}
	}

	@Override
	public  T populate(Report report) {
		return report.populate(scope);
	}

	@Override
	public  List> history(Class manifest, Collection uris) {
		return getHistoryRepository(manifest).find(uris);
	}

	@Override
	public  Observable> track(Class manifest) {
		if (changes == null) changes = scope.resolve(DataChangeNotification.class);
		return changes.track(manifest);
	}

	@Override
	public void commit() {
		if (hasChanges) {
			try {
				connection.commit();
			} catch (SQLException e) {
				throw new RuntimeException(e);
			}
		}
		hasChanges = false;
	}

	@Override
	public void rollback() {
		try {
			connection.rollback();
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
		hasChanges = false;
	}

	@Override
	public void close() throws IOException {
		if (closed) {
			return;
		}
		if (connection != null && manageConnection) {
			if (hasChanges) {
				rollback();
			}
			try {
				connection.setAutoCommit(true);
				connection.close();
			} catch (SQLException e) {
				throw new IOException(e);
			}
		}
		if (connection != null) {
			closed = true;
			try {
				scope.close();
			} catch (Exception e) {
				throw new IOException(e);
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy