org.fuchss.objectcasket.objectpacker.impl.JoinTableBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of object-casket Show documentation
Show all versions of object-casket Show documentation
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.
package org.fuchss.objectcasket.objectpacker.impl;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.fuchss.objectcasket.common.CasketError.CE3;
import org.fuchss.objectcasket.common.CasketException;
import org.fuchss.objectcasket.objectpacker.port.Session;
import org.fuchss.objectcasket.tablemodule.port.Row;
import org.fuchss.objectcasket.tablemodule.port.Table;
import org.fuchss.objectcasket.tablemodule.port.TableModule;
import org.fuchss.objectcasket.tablemodule.port.TableObserver;
class JoinTableBuilder implements TableObserver {
private static final String PK_ID = "pk@id";
private static final String CLIENT_ID = "client@id";
private static final String SUPPLIER_ID = "supplier@id";
private static final Class extends Serializable> PK_TYPE = Integer.class;
private final SessionImpl session;
private final TableModule tabMod;
private Table joinTable;
private final M2MInfo info;
private final Map> joinTabEntryMap = new HashMap<>();
private final Map rowToClientMap = new HashMap<>();
private final Map rowToSupplierMap = new HashMap<>();
private final Map supplierKeyMap = new HashMap<>();
JoinTableBuilder(SessionImpl sessionImpl, TableModule tableModule, M2MInfo info) throws CasketException {
this.info = info;
this.session = sessionImpl;
this.tabMod = tableModule;
this.createTableOrView();
}
Class getSupplierClass() {
return this.info.getSupplierClass();
}
int write(C client, Set suppliers, Object transaction) throws CasketException, IllegalArgumentException, IllegalAccessException {
Set currentSuppliers = this.joinTabEntryMap.computeIfAbsent(client, k -> new HashMap<>()).keySet();
boolean hasSuppliers = !currentSuppliers.isEmpty();
Set newSuppliers = new HashSet<>(suppliers);
newSuppliers.removeAll(currentSuppliers);
Set removedSuppliers = new HashSet<>(currentSuppliers);
removedSuppliers.removeAll(suppliers);
this.deleteRow(client, removedSuppliers, transaction);
this.createRows(client, newSuppliers, transaction);
for (S supplier : newSuppliers)
this.session.addClient(supplier);
for (S supplier : removedSuppliers)
this.session.removeClient(this.info.getSupplierClass(), this.info.getSupplierClassInfo().getPK(supplier));
if (hasSuppliers)
return (suppliers.isEmpty() ? -1 : 0);
return (!suppliers.isEmpty() ? 1 : 0);
}
Set allSuppliers(C obj, Object transaction) throws CasketException {
try {
if (!this.joinTabEntryMap.containsKey(obj)) {
Map newJoinTabEntries = new HashMap<>();
this.readSuppliers(obj, newJoinTabEntries, transaction);
this.joinTabEntryMap.put(obj, newJoinTabEntries);
}
return new HashSet<>(this.joinTabEntryMap.get(obj).keySet());
} catch (Exception exc) {
throw CasketException.build(exc);
}
}
private void createTableOrView() throws CasketException {
Map> signature = new HashMap<>();
signature.put(SUPPLIER_ID, this.info.getSupplierClassInfo().getType());
signature.put(CLIENT_ID, this.info.getClientClassInfo().getType());
signature.put(PK_ID, PK_TYPE);
if (this.tabMod.tableExists(this.info.getJoinTableName()))
this.joinTable = this.tabMod.mkView(this.info.getJoinTableName(), PK_ID, signature, true);
else
this.joinTable = this.tabMod.createTable(this.info.getJoinTableName(), PK_ID, signature, true);
this.joinTable.register(this);
}
private void createRows(C client, Set newSuppliers, Object transaction) throws IllegalArgumentException, IllegalAccessException, CasketException {
Map joinTabEntries = this.joinTabEntryMap.get(client);
Serializable clientPk = this.info.getClientClassInfo().getPK(client);
for (S supplier : newSuppliers) {
Map newValues = new HashMap<>();
newValues.put(CLIENT_ID, clientPk);
newValues.put(SUPPLIER_ID, this.info.getSupplierClassInfo().getPK(supplier));
Row row = this.joinTable.createRow(newValues, transaction);
joinTabEntries.put(supplier, row);
this.rowToClientMap.put(row, client);
this.rowToSupplierMap.put(row, supplier);
}
}
private void deleteRow(C client, Set removedSuppliers, Object transaction) throws CasketException {
Map joinTabEntries = this.joinTabEntryMap.get(client);
for (S supplier : removedSuppliers) {
Row joinTabRow = joinTabEntries.remove(supplier);
this.joinTable.deleteRow(joinTabRow, transaction);
this.rowToClientMap.remove(joinTabRow);
this.rowToSupplierMap.remove(joinTabRow);
}
}
private void readSuppliers(C obj, Map newJoinTabEntries, Object transaction) throws IllegalArgumentException, IllegalAccessException, CasketException {
Set args = new HashSet<>();
args.add(new Table.Exp(CLIENT_ID, Table.TabCMP.EQUAL, this.info.getClientClassInfo().getPK(obj)));
List rows = this.joinTable.searchRows(args, transaction);
for (Row row : rows) {
Serializable fk = row.getValue(SUPPLIER_ID, this.info.getSupplierClassInfo().getType());
Set arg = new HashSet<>();
arg.add(new Session.Exp(this.info.getSupplierClassInfo().getFieldName(), "==", fk));
S supplier = this.session.getObjects(this.info.getSupplierClass(), arg).iterator().next();
this.rowToClientMap.put(row, obj);
this.rowToSupplierMap.put(row, supplier);
newJoinTabEntries.put(supplier, row);
}
}
@SuppressWarnings("unchecked")
@Override
public synchronized void update(Set changed, Set deleted, Set added) {
synchronized (this.session) {
if (this.session.ignore)
return;
try {
ObjectBuilder clientBuilder = (ObjectBuilder) this.session.objectFactoryMap.getIfExists(this.info.getClientClass());
ObjectBuilder supplierBuilder = (ObjectBuilder) this.session.objectFactoryMap.getIfExists(this.info.getSupplierClass());
Set changedClients = new HashSet<>();
Set changedSuppliers = new HashSet<>();
Set suppliersToLoad = new HashSet<>();
for (Row row : deleted) {
S supplier = this.rowToSupplierMap.remove(row);
C client = this.rowToClientMap.remove(row);
if ((client != null) && (supplier != null)) {
this.joinTabEntryMap.get(client).remove(supplier);
changedClients.add(client);
}
}
for (Row row : added) {
Serializable clientKey = row.getValue(CLIENT_ID, this.info.getClientClassInfo().getType());
C client = clientBuilder.getObjectByPk(clientKey);
if (client == null)
continue;
Serializable supplierKey = row.getValue(SUPPLIER_ID, this.info.getSupplierClassInfo().getType());
S supplier = supplierBuilder.getObjectByPk(supplierKey);
if (supplier == null)
suppliersToLoad.add(supplierKey);
else
changedSuppliers.add(supplier);
changedClients.add(client);
this.setMaps(row, client, supplier, supplierKey);
}
this.informBuilderAndSession(suppliersToLoad, changedClients, changedSuppliers, clientBuilder, supplierBuilder);
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
private void setMaps(Row row, C client, S supplier, Serializable supplierKey) throws CasketException {
if ((supplier == null) && (supplierKey == null))
throw CE3.MISSING_SUPPLIER.defaultBuild(client, row, this.info.getJoinTableName());
this.rowToClientMap.put(row, client);
if (supplier == null)
this.supplierKeyMap.put(supplierKey, row);
else {
this.rowToSupplierMap.put(row, supplier);
this.joinTabEntryMap.get(client).put(supplier, row);
}
}
private void informBuilderAndSession(Set suppliersToLoad, Set changedClients, Set changedSuppliers, ObjectBuilder clientBuilder, ObjectBuilder supplierBuilder) {
if (changedClients.isEmpty() && changedSuppliers.isEmpty() && suppliersToLoad.isEmpty())
return;
if (!changedClients.isEmpty())
clientBuilder.changedObjects(changedClients);
if (!changedSuppliers.isEmpty())
supplierBuilder.changedObjects(changedSuppliers);
if (!suppliersToLoad.isEmpty())
this.session.loadNewAssignedObjects(this, suppliersToLoad, this.info.getSupplierClassInfo().getFieldName());
this.session.updateDone();
}
@SuppressWarnings("unchecked")
protected void insertNewSuppliers(Map supplierMap) {
for (Entry entry : supplierMap.entrySet()) {
Row row = this.supplierKeyMap.remove(entry.getKey());
C client = this.rowToClientMap.get(row);
S supplier = (S) entry.getValue();
this.rowToSupplierMap.put(row, supplier);
this.joinTabEntryMap.computeIfAbsent(client, k -> new HashMap<>()).put(supplier, row);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy