diff --git a/src/main/java/org/caosdb/server/database/BackendTransaction.java b/src/main/java/org/caosdb/server/database/BackendTransaction.java index 5addf3f3f3e34a8e3e6a9152b9511046fe4b6a23..05ea26c255ae5b2bd1e75df7f3fdc4d94fca5e5a 100644 --- a/src/main/java/org/caosdb/server/database/BackendTransaction.java +++ b/src/main/java/org/caosdb/server/database/BackendTransaction.java @@ -47,7 +47,6 @@ import org.caosdb.server.database.backend.implementation.MySQL.MySQLIsSubType; import org.caosdb.server.database.backend.implementation.MySQL.MySQLListRoles; import org.caosdb.server.database.backend.implementation.MySQL.MySQLListUsers; import org.caosdb.server.database.backend.implementation.MySQL.MySQLLogUserVisit; -import org.caosdb.server.database.backend.implementation.MySQL.MySQLRegisterSubDomain; import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveAll; import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveAllUncheckedFiles; import org.caosdb.server.database.backend.implementation.MySQL.MySQLRetrieveDatatypes; @@ -106,7 +105,6 @@ import org.caosdb.server.database.backend.interfaces.IsSubTypeImpl; import org.caosdb.server.database.backend.interfaces.ListRolesImpl; import org.caosdb.server.database.backend.interfaces.ListUsersImpl; import org.caosdb.server.database.backend.interfaces.LogUserVisitImpl; -import org.caosdb.server.database.backend.interfaces.RegisterSubDomainImpl; import org.caosdb.server.database.backend.interfaces.RetrieveAllImpl; import org.caosdb.server.database.backend.interfaces.RetrieveAllUncheckedFilesImpl; import org.caosdb.server.database.backend.interfaces.RetrieveDatatypesImpl; @@ -177,7 +175,6 @@ public abstract class BackendTransaction implements Undoable { setImpl(IsSubTypeImpl.class, MySQLIsSubType.class); setImpl(UpdateSparseEntityImpl.class, MySQLUpdateSparseEntity.class); setImpl(RetrieveAllImpl.class, MySQLRetrieveAll.class); - setImpl(RegisterSubDomainImpl.class, MySQLRegisterSubDomain.class); setImpl(RetrieveDatatypesImpl.class, MySQLRetrieveDatatypes.class); setImpl(RetrieveUserImpl.class, MySQLRetrieveUser.class); setImpl(RetrieveParentsImpl.class, MySQLRetrieveParents.class); diff --git a/src/main/java/org/caosdb/server/database/DatabaseUtils.java b/src/main/java/org/caosdb/server/database/DatabaseUtils.java index 5799d23faf3435e9bb939666770aedd7a0a6c00b..6d72d96546b0df7f98d46ab9cce2c32fe0d0c15d 100644 --- a/src/main/java/org/caosdb/server/database/DatabaseUtils.java +++ b/src/main/java/org/caosdb/server/database/DatabaseUtils.java @@ -27,6 +27,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; +import java.util.Deque; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; @@ -44,9 +45,7 @@ import org.caosdb.server.entity.EntityID; import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.entity.Message; import org.caosdb.server.entity.RetrieveEntity; -import org.caosdb.server.entity.Role; import org.caosdb.server.entity.StatementStatus; -import org.caosdb.server.entity.wrapper.Domain; import org.caosdb.server.entity.wrapper.Parent; import org.caosdb.server.entity.wrapper.Property; @@ -63,39 +62,33 @@ public class DatabaseUtils { } } - private static Domain makeReplacement(final EntityInterface p) { - // add a new helper domain. - final Domain d = - new Domain(p.getProperties(), p.getDatatype(), p.getValue(), p.getStatementStatus()); - d.setDescOverride(p.isDescOverride()); - d.setNameOverride(p.isNameOverride()); - d.setDatatypeOverride(p.isDatatypeOverride()); - d.setName(p.getName()); - d.setDescription(p.getDescription()); - p.setReplacement(d); - return d; - } - - public static void deriveStage1Inserts( - final List<EntityInterface> stage1Inserts, final EntityInterface e) { + public static int deriveStage1Inserts( + final List<Property> stage1Inserts, final EntityInterface e) { // entity value if (e.hasValue()) { final Property p = new Property(e); p.setStatementStatus(StatementStatus.FIX); - p.setPIdx(0); p.setDatatype(e.getDatatype()); p.setValue(e.getValue()); + p.setPIdx(0); processPropertiesStage1(stage1Inserts, p, e); } - for (final EntityInterface p : e.getProperties()) { + for (final Property p : e.getProperties()) { processPropertiesStage1(stage1Inserts, p, e); } + int replacementCount = 0; + for (EntityInterface pp : stage1Inserts) { + if (pp instanceof Replacement) { + replacementCount++; + } + } + return replacementCount; } private static void processPropertiesStage1( - final List<EntityInterface> stage1Inserts, final EntityInterface p, final EntityInterface e) { - stage1Inserts.add(p); + final List<Property> stage1Inserts, final Property p, final EntityInterface e) { + if (!p.isDescOverride() && !p.isNameOverride() && !p.isDatatypeOverride() @@ -105,25 +98,40 @@ public class DatabaseUtils { // setReplacement(null) because there is a corner case (related to the inheritance of // properties) where there is a replacement present which belongs to the parent entity, see // https://gitlab.com/caosdb/caosdb-server/-/issues/216. - p.setReplacement(null); + stage1Inserts.add(p); } else { - stage1Inserts.add(makeReplacement(p)); + Replacement r = new Replacement(p); + stage1Inserts.add(r); + stage1Inserts.add(r.replacement); } processSubPropertiesStage1(stage1Inserts, p); } - public static int deriveStage2Inserts( - final List<EntityInterface> stage2Inserts, final List<EntityInterface> stage1Inserts) { - int domainCount = 0; - for (final EntityInterface p : stage1Inserts) { - if (p.hasRole() && p.getRole() == Role.Domain) { - domainCount++; - } - if (!p.hasReplacement() && p.hasProperties()) { - stage2Inserts.addAll(p.getProperties()); + public static void deriveStage2Inserts( + final List<Property> stage2Inserts, + final List<Property> stage1Inserts, + Deque<EntityID> replacementIds, + EntityInterface entity) { + for (final Property p : stage1Inserts) { + if (p instanceof Replacement) { + + EntityID replacementId = replacementIds.pop(); + ((Replacement) p).setReplacementId(replacementId); + + if (p.hasProperties()) { + for (Property subP : p.getProperties()) { + subP.setDomain(p); + stage2Inserts.add(subP); + } + } + } else { + if (p.hasProperties()) { + for (Property subP : p.getProperties()) { + stage2Inserts.add(subP); + } + } } } - return domainCount; } private static boolean hasUniquePropertyId(final EntityInterface p, final EntityInterface e) { @@ -137,10 +145,10 @@ public class DatabaseUtils { } private static void processSubPropertiesStage1( - final List<EntityInterface> stage1Inserts, final EntityInterface p) { - for (final EntityInterface subP : p.getProperties()) { + final List<Property> stage1Inserts, final EntityInterface p) { + for (final Property subP : p.getProperties()) { if (subP.hasProperties()) { - stage1Inserts.add(makeReplacement(subP)); + stage1Inserts.add(new Replacement(subP)); processSubPropertiesStage1(stage1Inserts, subP); } } diff --git a/src/main/java/org/caosdb/server/database/Replacement.java b/src/main/java/org/caosdb/server/database/Replacement.java new file mode 100644 index 0000000000000000000000000000000000000000..8606d51bcf903eccea77132aaed9e6a7541da71e --- /dev/null +++ b/src/main/java/org/caosdb/server/database/Replacement.java @@ -0,0 +1,41 @@ +package org.caosdb.server.database; + +import org.caosdb.server.datatype.ReferenceValue; +import org.caosdb.server.entity.EntityID; +import org.caosdb.server.entity.RetrieveEntity; +import org.caosdb.server.entity.StatementStatus; +import org.caosdb.server.entity.wrapper.Property; + +public class Replacement extends Property { + + public Property replacement; + public EntityID replacementId; + + @Override + public EntityID getId() { + return replacementId; + } + + public void setReplacementId(EntityID id) { + replacementId.link(id); + } + + public Replacement(Property p) { + super(p); + replacementId = new EntityID(); + replacement = new Property(new RetrieveEntity()); + + replacement.setDomain(p.getDomainEntity()); + // replacement.setDatatypeOverride(p.isDatatypeOverride()); + // replacement.setDatatype(p.getDatatype()); + // replacement.setNameOverride(p.isNameOverride()); + // replacement.setName(p.getName()); + // replacement.setDescOverride(p.isDescOverride()); + // replacement.setDescription(p.getDescription()); + + replacement.setId(replacementId); + replacement.setStatementStatus(StatementStatus.REPLACEMENT); + replacement.setValue(new ReferenceValue(p.getId())); + replacement.setPIdx(0); + } +} diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertEntityProperties.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertEntityProperties.java index 7c3c5a33e160f3da6a8c2b89fe0487e0317c99da..5c9ca6f9bbda94f63e93054c9b5a508de0b5d4e7 100644 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertEntityProperties.java +++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertEntityProperties.java @@ -25,15 +25,30 @@ package org.caosdb.server.database.backend.implementation.MySQL; import static java.sql.Types.BIGINT; import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLIntegrityConstraintViolationException; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import org.caosdb.server.database.DatabaseUtils; import org.caosdb.server.database.access.Access; import org.caosdb.server.database.backend.interfaces.InsertEntityPropertiesImpl; import org.caosdb.server.database.exceptions.IntegrityException; import org.caosdb.server.database.exceptions.TransactionException; import org.caosdb.server.database.proto.FlatProperty; +import org.caosdb.server.datatype.AbstractCollectionDatatype; import org.caosdb.server.datatype.AbstractDatatype.Table; +import org.caosdb.server.datatype.CollectionValue; +import org.caosdb.server.datatype.IndexedSingleValue; +import org.caosdb.server.datatype.ReferenceValue; +import org.caosdb.server.datatype.SingleValue; import org.caosdb.server.entity.EntityID; +import org.caosdb.server.entity.EntityInterface; +import org.caosdb.server.entity.StatementStatus; +import org.caosdb.server.entity.wrapper.Property; public class MySQLInsertEntityProperties extends MySQLTransaction implements InsertEntityPropertiesImpl { @@ -46,7 +61,27 @@ public class MySQLInsertEntityProperties extends MySQLTransaction } @Override - public void execute( + public void execute(EntityInterface entity) { + final List<Property> stage1Inserts = new LinkedList<>(); + final List<Property> stage2Inserts = new LinkedList<>(); + + final int domainCount = DatabaseUtils.deriveStage1Inserts(stage1Inserts, entity); + + try { + final Deque<EntityID> replacementIds = registerReplacementId(domainCount); + + DatabaseUtils.deriveStage2Inserts(stage2Inserts, stage1Inserts, replacementIds, entity); + + insertStages(stage1Inserts, entity.getDomain(), entity.getId()); + insertStages(stage2Inserts, entity.getId(), null); + } catch (final SQLIntegrityConstraintViolationException exc) { + throw new IntegrityException(exc); + } catch (SQLException | ConnectionException e) { + throw new TransactionException(e); + } + } + + private void insertFlatProperty( final EntityID domain, final EntityID entity, final FlatProperty fp, @@ -76,10 +111,114 @@ public class MySQLInsertEntityProperties extends MySQLTransaction stmt.execute(); } catch (final SQLIntegrityConstraintViolationException exc) { throw new IntegrityException(exc); - } catch (final SQLException exc) { - throw new TransactionException(exc); - } catch (final ConnectionException exc) { + } catch (final SQLException | ConnectionException exc) { throw new TransactionException(exc); } } + + private void insertStages( + final List<Property> stage1Inserts, final EntityID domain, final EntityID entity) + throws TransactionException { + + for (final Property property : stage1Inserts) { + + // prepare flat property + final FlatProperty fp = new FlatProperty(); + Table table = Table.null_data; + Long unit_sig = null; + fp.id = property.getId().toInteger(); + fp.idx = property.getPIdx(); + fp.status = property.getStatementStatus().name(); + + if (property.getStatementStatus() == StatementStatus.REPLACEMENT) { + table = Table.reference_data; + fp.value = fp.id.toString(); + fp.id = ((ReferenceValue) property.getValue()).getId().toInteger(); + } else { + + if (property.hasUnit()) { + unit_sig = property.getUnit().getSignature(); + } + if (property.hasValue()) { + if (property.getValue() instanceof CollectionValue) { + // insert collection of values + final CollectionValue v = (CollectionValue) property.getValue(); + final Iterator<IndexedSingleValue> iterator = v.iterator(); + final SingleValue firstValue = iterator.next(); + + // insert 2nd to nth item + for (int i = 1; i < v.size(); i++) { + final SingleValue vi = iterator.next(); + fp.idx = i; + if (vi == null) { + fp.value = null; + table = Table.null_data; + } else { + fp.value = vi.toDatabaseString(); + table = vi.getTable(); + } + insertFlatProperty( + domain, entity != null ? entity : property.getDomain(), fp, table, unit_sig); + } + + // insert first item + fp.idx = 0; + if (firstValue == null) { + fp.value = null; + table = Table.null_data; + } else { + fp.value = firstValue.toDatabaseString(); + table = firstValue.getTable(); + } + + } else { + // insert single value + fp.value = ((SingleValue) property.getValue()).toDatabaseString(); + if (property instanceof Property && ((Property) property).isName()) { + table = Table.name_data; + } else { + table = ((SingleValue) property.getValue()).getTable(); + } + } + } + if (property.isNameOverride()) { + fp.name = property.getName(); + } + if (property.isDescOverride()) { + fp.desc = property.getDescription(); + } + if (property.isDatatypeOverride()) { + if (property.getDatatype() instanceof AbstractCollectionDatatype) { + fp.type = + ((AbstractCollectionDatatype) property.getDatatype()) + .getDatatype() + .getId() + .toString(); + fp.collection = + ((AbstractCollectionDatatype) property.getDatatype()).getCollectionName(); + } else { + fp.type = property.getDatatype().getId().toString(); + } + } + } + + insertFlatProperty( + domain, entity != null ? entity : property.getDomain(), fp, table, unit_sig); + } + } + + public static final String STMT_REGISTER_SUBDOMAIN = "call registerSubdomain(?)"; + + public Deque<EntityID> registerReplacementId(final int domainCount) + throws SQLException, ConnectionException { + final PreparedStatement stmt = prepareStatement(STMT_REGISTER_SUBDOMAIN); + stmt.setInt(1, domainCount); + try (final ResultSet rs = stmt.executeQuery()) { + final Deque<EntityID> ret = new ArrayDeque<>(); + while (rs.next()) { + ret.add(new EntityID(rs.getInt(1))); + } + return ret; + } + } } diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRegisterSubDomain.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRegisterSubDomain.java deleted file mode 100644 index 1e14600e71023dff544a09910fabe0dc8b17ca42..0000000000000000000000000000000000000000 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRegisterSubDomain.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * ** header v3.0 - * This file is a part of the CaosDB Project. - * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * - * 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 <https://www.gnu.org/licenses/>. - * - * ** end header - */ -package org.caosdb.server.database.backend.implementation.MySQL; - -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayDeque; -import java.util.Deque; -import org.caosdb.server.database.access.Access; -import org.caosdb.server.database.backend.interfaces.RegisterSubDomainImpl; -import org.caosdb.server.database.exceptions.TransactionException; -import org.caosdb.server.entity.EntityID; - -public class MySQLRegisterSubDomain extends MySQLTransaction implements RegisterSubDomainImpl { - - public MySQLRegisterSubDomain(final Access access) { - super(access); - } - - public static final String STMT_REGISTER_SUBDOMAIN = "call registerSubdomain(?)"; - - @Override - public Deque<EntityID> execute(final int domainCount) throws TransactionException { - try { - final PreparedStatement stmt = prepareStatement(STMT_REGISTER_SUBDOMAIN); - stmt.setInt(1, domainCount); - final ResultSet rs = stmt.executeQuery(); - try { - final Deque<EntityID> ret = new ArrayDeque<>(); - while (rs.next()) { - ret.add(new EntityID(rs.getInt(1))); - } - return ret; - } finally { - rs.close(); - } - } catch (final SQLException e) { - throw new TransactionException(e); - } catch (final ConnectionException e) { - throw new TransactionException(e); - } - } -} diff --git a/src/main/java/org/caosdb/server/database/backend/interfaces/InsertEntityPropertiesImpl.java b/src/main/java/org/caosdb/server/database/backend/interfaces/InsertEntityPropertiesImpl.java index 2406d4895487bdec5f271b41bf46207a48c7375d..f17643fd6ff0e980aef122a318fd9fc2668e2b79 100644 --- a/src/main/java/org/caosdb/server/database/backend/interfaces/InsertEntityPropertiesImpl.java +++ b/src/main/java/org/caosdb/server/database/backend/interfaces/InsertEntityPropertiesImpl.java @@ -22,15 +22,10 @@ */ package org.caosdb.server.database.backend.interfaces; -import org.caosdb.server.database.exceptions.TransactionException; -import org.caosdb.server.database.proto.FlatProperty; -import org.caosdb.server.datatype.AbstractDatatype.Table; -import org.caosdb.server.entity.EntityID; +import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.utils.Undoable; public interface InsertEntityPropertiesImpl extends BackendTransactionImpl, Undoable { - public abstract void execute( - EntityID domain, EntityID entity, FlatProperty fp, Table table, Long unit_sig) - throws TransactionException; + public abstract void execute(EntityInterface entity); } diff --git a/src/main/java/org/caosdb/server/database/backend/interfaces/RegisterSubDomainImpl.java b/src/main/java/org/caosdb/server/database/backend/interfaces/RegisterSubDomainImpl.java deleted file mode 100644 index 87ea0c85db6a698f49c103506b520342deff2fb0..0000000000000000000000000000000000000000 --- a/src/main/java/org/caosdb/server/database/backend/interfaces/RegisterSubDomainImpl.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * ** header v3.0 - * This file is a part of the CaosDB Project. - * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * - * 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 <https://www.gnu.org/licenses/>. - * - * ** end header - */ -package org.caosdb.server.database.backend.interfaces; - -import java.util.Deque; -import org.caosdb.server.database.exceptions.TransactionException; -import org.caosdb.server.entity.EntityID; - -public interface RegisterSubDomainImpl extends BackendTransactionImpl { - - public abstract Deque<EntityID> execute(int domainCount) throws TransactionException; -} diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityProperties.java b/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityProperties.java index f9af6a482efaccf896a1a85fc65d0e1217bd6a53..8de8afc084ae16dea370a519a4fde3524fa8c7c9 100644 --- a/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityProperties.java +++ b/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityProperties.java @@ -22,25 +22,10 @@ */ package org.caosdb.server.database.backend.transaction; -import java.util.ArrayList; -import java.util.Deque; -import java.util.Iterator; -import java.util.List; import org.caosdb.server.database.BackendTransaction; -import org.caosdb.server.database.DatabaseUtils; import org.caosdb.server.database.backend.interfaces.InsertEntityPropertiesImpl; import org.caosdb.server.database.exceptions.TransactionException; -import org.caosdb.server.database.proto.FlatProperty; -import org.caosdb.server.datatype.AbstractCollectionDatatype; -import org.caosdb.server.datatype.AbstractDatatype.Table; -import org.caosdb.server.datatype.CollectionValue; -import org.caosdb.server.datatype.IndexedSingleValue; -import org.caosdb.server.datatype.SingleValue; -import org.caosdb.server.entity.EntityID; import org.caosdb.server.entity.EntityInterface; -import org.caosdb.server.entity.Role; -import org.caosdb.server.entity.StatementStatus; -import org.caosdb.server.entity.wrapper.Property; public class InsertEntityProperties extends BackendTransaction { @@ -54,126 +39,6 @@ public class InsertEntityProperties extends BackendTransaction { public void execute() throws TransactionException { final InsertEntityPropertiesImpl t = getImplementation(InsertEntityPropertiesImpl.class); - - final ArrayList<EntityInterface> stage1Inserts = new ArrayList<EntityInterface>(); - final ArrayList<EntityInterface> stage2Inserts = new ArrayList<EntityInterface>(); - - DatabaseUtils.deriveStage1Inserts(stage1Inserts, this.entity); - - final int domainCount = DatabaseUtils.deriveStage2Inserts(stage2Inserts, stage1Inserts); - - final Deque<EntityID> domainIds = execute(new RegisterSubDomain(domainCount)).getDomains(); - - insertStages(t, domainIds, stage1Inserts, this.entity.getDomain(), this.entity.getId()); - insertStages(t, domainIds, stage2Inserts, this.entity.getId(), null); - } - - private void insertStages( - final InsertEntityPropertiesImpl t, - final Deque<EntityID> domainIds, - final List<EntityInterface> stage1Inserts, - final EntityID domain, - final EntityID entity) - throws TransactionException { - - for (final EntityInterface property : stage1Inserts) { - if (property.hasRole() && property.getRole() == Role.Domain && !property.hasId()) { - property.setId(domainIds.removeFirst()); - } - int pIdx; - if (property instanceof Property) { - // this is a normal property - pIdx = ((Property) property).getPIdx(); - } else { - // this is a replacement - pIdx = 0; - } - - // prepare flat property - final FlatProperty fp = new FlatProperty(); - Table table = Table.null_data; - Long unit_sig = null; - fp.id = property.getId().toInteger(); - fp.idx = pIdx; - - if (property.hasReplacement()) { - if (!property.getReplacement().hasId()) { - property.getReplacement().setId(domainIds.removeFirst()); - } - - fp.value = property.getReplacement().getId().toString(); - fp.status = StatementStatus.REPLACEMENT.toString(); - - table = Table.reference_data; - } else { - if (property.hasUnit()) { - unit_sig = property.getUnit().getSignature(); - } - fp.status = property.getStatementStatus().toString(); - if (property.hasValue()) { - if (property.getValue() instanceof CollectionValue) { - // insert collection of values - final CollectionValue v = (CollectionValue) property.getValue(); - final Iterator<IndexedSingleValue> iterator = v.iterator(); - final SingleValue firstValue = iterator.next(); - - // insert 2nd to nth item - for (int i = 1; i < v.size(); i++) { - final SingleValue vi = iterator.next(); - fp.idx = i; - if (vi == null) { - fp.value = null; - table = Table.null_data; - } else { - fp.value = vi.toDatabaseString(); - table = vi.getTable(); - } - t.execute( - domain, entity != null ? entity : property.getDomain(), fp, table, unit_sig); - } - - // insert first item - fp.idx = 0; - if (firstValue == null) { - fp.value = null; - table = Table.null_data; - } else { - fp.value = firstValue.toDatabaseString(); - table = firstValue.getTable(); - } - - } else { - // insert single value - fp.value = ((SingleValue) property.getValue()).toDatabaseString(); - if (property instanceof Property && ((Property) property).isName()) { - table = Table.name_data; - } else { - table = ((SingleValue) property.getValue()).getTable(); - } - } - } - if (property.isNameOverride()) { - fp.name = property.getName(); - } - if (property.isDescOverride()) { - fp.desc = property.getDescription(); - } - if (property.isDatatypeOverride()) { - if (property.getDatatype() instanceof AbstractCollectionDatatype) { - fp.type = - ((AbstractCollectionDatatype) property.getDatatype()) - .getDatatype() - .getId() - .toString(); - fp.collection = - ((AbstractCollectionDatatype) property.getDatatype()).getCollectionName(); - } else { - fp.type = property.getDatatype().getId().toString(); - } - } - } - - t.execute(domain, entity != null ? entity : property.getDomain(), fp, table, unit_sig); - } + t.execute(this.entity); } } diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityTransaction.java b/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityTransaction.java index 5871c97e8ff172fe58b37627cc93824e96c7b32e..2846fa64d56ea696d4ecb0412a88de449d0483a1 100644 --- a/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityTransaction.java +++ b/src/main/java/org/caosdb/server/database/backend/transaction/InsertEntityTransaction.java @@ -54,7 +54,9 @@ public class InsertEntityTransaction extends BackendTransaction { if (newEntity.hasFileProperties()) { execute(new InsertFile(newEntity)); } - execute(new InsertEntityProperties(newEntity)); + if (newEntity.hasProperties() || newEntity.hasValue()) { + execute(new InsertEntityProperties(newEntity)); + } execute(new InsertParents(newEntity)); if (newEntity.getEntityStatus() == EntityStatus.QUALIFIED) { diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/RegisterSubDomain.java b/src/main/java/org/caosdb/server/database/backend/transaction/RegisterSubDomain.java deleted file mode 100644 index 0321a621a82a9ae2841d31b55b05a46743f963bd..0000000000000000000000000000000000000000 --- a/src/main/java/org/caosdb/server/database/backend/transaction/RegisterSubDomain.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * ** header v3.0 - * This file is a part of the CaosDB Project. - * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * - * 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 <https://www.gnu.org/licenses/>. - * - * ** end header - */ -package org.caosdb.server.database.backend.transaction; - -import java.util.Deque; -import org.caosdb.server.database.BackendTransaction; -import org.caosdb.server.database.backend.interfaces.RegisterSubDomainImpl; -import org.caosdb.server.database.exceptions.TransactionException; -import org.caosdb.server.entity.EntityID; - -public class RegisterSubDomain extends BackendTransaction { - - private final int domainCount; - private Deque<EntityID> list; - - public RegisterSubDomain(final int domainCount) { - this.domainCount = domainCount; - } - - @Override - public void execute() throws TransactionException { - final RegisterSubDomainImpl t = getImplementation(RegisterSubDomainImpl.class); - this.list = t.execute(this.domainCount); - } - - public Deque<EntityID> getDomains() { - return this.list; - } -} diff --git a/src/main/java/org/caosdb/server/database/proto/FlatProperty.java b/src/main/java/org/caosdb/server/database/proto/FlatProperty.java index b92d3def38d26f0f5f6cd6a0455d472b8f4f3ccb..b4f0f62a2e5f596219180140a4905f5b20abe2d3 100644 --- a/src/main/java/org/caosdb/server/database/proto/FlatProperty.java +++ b/src/main/java/org/caosdb/server/database/proto/FlatProperty.java @@ -26,6 +26,19 @@ import java.io.Serializable; public class FlatProperty implements Serializable { + public FlatProperty() {} + + public FlatProperty(FlatProperty fp) { + id = fp.id; + value = fp.value; + status = fp.status; + idx = fp.idx; + name = fp.name; + desc = fp.desc; + type = fp.type; + collection = fp.collection; + } + private static final long serialVersionUID = 6039288034435124195L; public Integer id = null; public String value = null; diff --git a/src/main/java/org/caosdb/server/database/proto/ProtoProperty.java b/src/main/java/org/caosdb/server/database/proto/ProtoProperty.java index 898565aca9e7e346f76ff60b9fc45ea0b1547331..c6cdbd5495dfbd596fe5ef564b557257706835cb 100644 --- a/src/main/java/org/caosdb/server/database/proto/ProtoProperty.java +++ b/src/main/java/org/caosdb/server/database/proto/ProtoProperty.java @@ -26,21 +26,14 @@ import java.io.Serializable; import java.util.List; public class ProtoProperty extends FlatProperty implements Serializable { + private static final long serialVersionUID = 7731301985162924975L; public ProtoProperty(FlatProperty fp) { - id = fp.id; - value = fp.value; - status = fp.status; - idx = fp.idx; - name = fp.name; - desc = fp.desc; - type = fp.type; - collection = fp.collection; + super(fp); } public ProtoProperty() {} - private static final long serialVersionUID = 7731301985162924975L; public List<ProtoProperty> subProperties = null; public List<Object> collValues = null; } diff --git a/src/test/java/org/caosdb/server/database/InsertTest.java b/src/test/java/org/caosdb/server/database/InsertTest.java index 59aa6f55084edacc93ad371e5f55b16e72a940f5..e385d6cb2038496b5c90715347cd34e88b8c60c8 100644 --- a/src/test/java/org/caosdb/server/database/InsertTest.java +++ b/src/test/java/org/caosdb/server/database/InsertTest.java @@ -28,13 +28,15 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.util.ArrayDeque; +import java.util.Deque; import java.util.LinkedList; import org.caosdb.server.datatype.CollectionValue; import org.caosdb.server.datatype.GenericValue; +import org.caosdb.server.datatype.ReferenceValue; import org.caosdb.server.datatype.SingleValue; import org.caosdb.server.entity.Entity; import org.caosdb.server.entity.EntityID; -import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.entity.InsertEntity; import org.caosdb.server.entity.RetrieveEntity; import org.caosdb.server.entity.Role; @@ -44,6 +46,14 @@ import org.junit.jupiter.api.Test; public class InsertTest { + private Deque<EntityID> registerReplacementIds(int count) { + Deque<EntityID> replacementIds = new ArrayDeque<>(); + for (int i = 1; i < count + 1; i++) { + replacementIds.add(new EntityID(-i)); + } + return replacementIds; + } + /** * Record with very deep property tree. * @@ -122,85 +132,67 @@ public class InsertTest { p10.setStatementStatus(StatementStatus.OBLIGATORY); p9.addProperty(p10); - final LinkedList<EntityInterface> stage1Inserts = new LinkedList<EntityInterface>(); - final LinkedList<EntityInterface> stage2Inserts = new LinkedList<EntityInterface>(); + final LinkedList<Property> stage1Inserts = new LinkedList<>(); + final LinkedList<Property> stage2Inserts = new LinkedList<>(); - deriveStage1Inserts(stage1Inserts, r); + int replacementCount = deriveStage1Inserts(stage1Inserts, r); + assertEquals(3, replacementCount); + + deriveStage2Inserts(stage2Inserts, stage1Inserts, registerReplacementIds(replacementCount), r); assertEquals(7, stage1Inserts.size()); - assertEquals(Role.Property, stage1Inserts.get(0).getRole()); - assertEquals(new EntityID(1), stage1Inserts.get(0).getId()); + assertFalse(stage1Inserts.get(0) instanceof Replacement); + assertEquals(1, stage1Inserts.get(0).getId().toInteger()); assertEquals("V1", ((SingleValue) stage1Inserts.get(0).getValue()).toDatabaseString()); - assertFalse(stage1Inserts.get(0).hasReplacement()); - assertEquals(Role.Property, stage1Inserts.get(1).getRole()); - assertEquals(new EntityID(2), stage1Inserts.get(1).getId()); + assertFalse(stage1Inserts.get(1) instanceof Replacement); + assertEquals(2, stage1Inserts.get(1).getId().toInteger()); assertEquals("V2", ((SingleValue) stage1Inserts.get(1).getValue()).toDatabaseString()); - assertFalse(stage1Inserts.get(1).hasReplacement()); - assertEquals(Role.Property, stage1Inserts.get(2).getRole()); - assertEquals(new EntityID(4), stage1Inserts.get(2).getId()); + assertFalse(stage1Inserts.get(2) instanceof Replacement); + assertEquals(4, stage1Inserts.get(2).getId().toInteger()); assertEquals("V4", ((SingleValue) stage1Inserts.get(2).getValue()).toDatabaseString()); - assertFalse(stage1Inserts.get(2).hasReplacement()); - assertEquals(Role.Domain, stage1Inserts.get(3).getRole()); + assertTrue(stage1Inserts.get(3) instanceof Replacement); + assertEquals(5, stage1Inserts.get(3).getId().toInteger()); assertEquals("V5", ((SingleValue) stage1Inserts.get(3).getValue()).toDatabaseString()); - assertFalse(stage1Inserts.get(3).hasReplacement()); - assertEquals(Role.Property, stage1Inserts.get(4).getRole()); - assertEquals(new EntityID(7), stage1Inserts.get(4).getId()); + assertFalse(stage1Inserts.get(4) instanceof Replacement); + assertEquals(7, stage1Inserts.get(4).getId().toInteger()); assertEquals("V7", ((SingleValue) stage1Inserts.get(4).getValue()).toDatabaseString()); - assertFalse(stage1Inserts.get(4).hasReplacement()); - assertEquals(Role.Domain, stage1Inserts.get(5).getRole()); + assertTrue(stage1Inserts.get(5) instanceof Replacement); + assertEquals(8, stage1Inserts.get(5).getId().toInteger()); assertEquals("V8", ((SingleValue) stage1Inserts.get(5).getValue()).toDatabaseString()); - assertFalse(stage1Inserts.get(5).hasReplacement()); - assertEquals(Role.Domain, stage1Inserts.get(6).getRole()); + assertTrue(stage1Inserts.get(6) instanceof Replacement); + assertEquals(9, stage1Inserts.get(6).getId().toInteger()); assertEquals("V9", ((SingleValue) stage1Inserts.get(6).getValue()).toDatabaseString()); - assertFalse(stage1Inserts.get(6).hasReplacement()); - - deriveStage2Inserts(stage2Inserts, stage1Inserts); assertEquals(6, stage2Inserts.size()); - assertEquals(Role.Property, stage2Inserts.get(0).getRole()); assertEquals(new EntityID(3), stage2Inserts.get(0).getId()); assertEquals("V3", ((SingleValue) stage2Inserts.get(0).getValue()).toDatabaseString()); assertEquals(new EntityID(2), stage2Inserts.get(0).getDomain()); - assertFalse(stage2Inserts.get(0).hasReplacement()); - assertEquals(Role.Property, stage2Inserts.get(1).getRole()); assertEquals(new EntityID(5), stage2Inserts.get(1).getId()); assertEquals("V5", ((SingleValue) stage2Inserts.get(1).getValue()).toDatabaseString()); - assertTrue(stage2Inserts.get(1).hasReplacement()); assertEquals(new EntityID(4), stage2Inserts.get(1).getDomain()); - assertEquals(stage1Inserts.get(3), stage2Inserts.get(1).getReplacement()); - assertEquals(Role.Property, stage2Inserts.get(2).getRole()); assertEquals(new EntityID(6), stage2Inserts.get(2).getId()); assertEquals("V6", ((SingleValue) stage2Inserts.get(2).getValue()).toDatabaseString()); - assertEquals(new EntityID(5), stage2Inserts.get(2).getDomain()); - assertFalse(stage2Inserts.get(2).hasReplacement()); + assertEquals(new EntityID(-1), stage2Inserts.get(2).getDomain()); - assertEquals(Role.Property, stage2Inserts.get(3).getRole()); assertEquals(new EntityID(8), stage2Inserts.get(3).getId()); assertEquals("V8", ((SingleValue) stage2Inserts.get(3).getValue()).toDatabaseString()); - assertTrue(stage2Inserts.get(3).hasReplacement()); assertEquals(new EntityID(7), stage2Inserts.get(3).getDomain()); - assertEquals(stage1Inserts.get(5), stage2Inserts.get(3).getReplacement()); - assertEquals(Role.Property, stage2Inserts.get(4).getRole()); assertEquals(new EntityID(9), stage2Inserts.get(4).getId()); assertEquals("V9", ((SingleValue) stage2Inserts.get(4).getValue()).toDatabaseString()); - assertTrue(stage2Inserts.get(4).hasReplacement()); - assertEquals(new EntityID(8), stage2Inserts.get(4).getDomain()); - assertEquals(stage1Inserts.get(6), stage2Inserts.get(4).getReplacement()); + assertEquals(new EntityID(-2), stage2Inserts.get(4).getDomain()); - assertEquals(Role.Property, stage2Inserts.get(5).getRole()); assertEquals(new EntityID(10), stage2Inserts.get(5).getId()); assertEquals("V10", ((SingleValue) stage2Inserts.get(5).getValue()).toDatabaseString()); - assertEquals(new EntityID(9), stage2Inserts.get(5).getDomain()); - assertFalse(stage2Inserts.get(5).hasReplacement()); + assertEquals(new EntityID(-3), stage2Inserts.get(5).getDomain()); } /** @@ -233,34 +225,31 @@ public class InsertTest { subp.setStatementStatus(StatementStatus.FIX); p2.addProperty(subp); - final LinkedList<EntityInterface> stage1Inserts = new LinkedList<EntityInterface>(); - final LinkedList<EntityInterface> stage2Inserts = new LinkedList<EntityInterface>(); + final LinkedList<Property> stage1Inserts = new LinkedList<>(); + final LinkedList<Property> stage2Inserts = new LinkedList<>(); - deriveStage1Inserts(stage1Inserts, r); + int replacementCount = deriveStage1Inserts(stage1Inserts, r); + deriveStage2Inserts(stage2Inserts, stage1Inserts, registerReplacementIds(replacementCount), r); assertEquals(3, stage1Inserts.size()); - assertEquals(Role.Property, stage1Inserts.get(0).getRole()); + + assertFalse(stage1Inserts.get(0) instanceof Replacement); assertEquals(new EntityID(1), stage1Inserts.get(0).getId()); assertEquals("V1-1", ((SingleValue) stage1Inserts.get(0).getValue()).toDatabaseString()); - assertFalse(stage1Inserts.get(0).hasReplacement()); - assertEquals(Role.Property, stage1Inserts.get(1).getRole()); + assertTrue(stage1Inserts.get(1) instanceof Replacement); assertEquals("V1-2", ((SingleValue) stage1Inserts.get(1).getValue()).toDatabaseString()); assertEquals(new EntityID(1), stage1Inserts.get(1).getId()); - assertTrue(stage1Inserts.get(1).hasReplacement()); - assertEquals(stage1Inserts.get(2), stage1Inserts.get(1).getReplacement()); - - assertEquals(Role.Domain, stage1Inserts.get(2).getRole()); - assertEquals("V1-2", ((SingleValue) stage1Inserts.get(2).getValue()).toDatabaseString()); - assertFalse(stage1Inserts.get(2).hasReplacement()); - deriveStage2Inserts(stage2Inserts, stage1Inserts); + assertFalse(stage1Inserts.get(2) instanceof Replacement); + assertEquals(new EntityID(-1), stage1Inserts.get(2).getId()); + assertEquals("1", ((SingleValue) stage1Inserts.get(2).getValue()).toDatabaseString()); assertEquals(1, stage2Inserts.size()); - assertEquals(Role.Property, stage2Inserts.get(0).getRole()); + + assertFalse(stage2Inserts.get(0) instanceof Replacement); assertEquals(new EntityID(2), stage2Inserts.get(0).getId()); assertEquals("V2", ((SingleValue) stage2Inserts.get(0).getValue()).toDatabaseString()); - assertFalse(stage2Inserts.get(0).hasReplacement()); } /** @@ -297,39 +286,33 @@ public class InsertTest { sub1.setStatementStatus(StatementStatus.FIX); p1.addProperty(sub1); - final LinkedList<EntityInterface> stage1Inserts = new LinkedList<EntityInterface>(); - final LinkedList<EntityInterface> stage2Inserts = new LinkedList<EntityInterface>(); + final LinkedList<Property> stage1Inserts = new LinkedList<>(); + final LinkedList<Property> stage2Inserts = new LinkedList<>(); - deriveStage1Inserts(stage1Inserts, r); + int count = deriveStage1Inserts(stage1Inserts, r); + deriveStage2Inserts(stage2Inserts, stage1Inserts, registerReplacementIds(count), r); assertEquals(4, stage1Inserts.size()); - assertEquals(Role.Property, stage1Inserts.get(0).getRole()); + assertTrue(stage1Inserts.get(0) instanceof Replacement); assertEquals(new EntityID(1), stage1Inserts.get(0).getId()); - assertTrue(stage1Inserts.get(0).hasReplacement()); - assertEquals(stage1Inserts.get(1), stage1Inserts.get(0).getReplacement()); assertEquals(null, stage1Inserts.get(0).getValue()); - assertEquals(Role.Domain, stage1Inserts.get(1).getRole()); - assertFalse(stage1Inserts.get(1).hasReplacement()); - assertEquals(null, stage1Inserts.get(1).getValue()); + assertFalse(stage1Inserts.get(1) instanceof Replacement); + assertEquals(new EntityID(-1), stage1Inserts.get(1).getId()); + assertEquals(1, ((ReferenceValue) stage1Inserts.get(1).getValue()).getId().toInteger()); - assertEquals(Role.Property, stage1Inserts.get(2).getRole()); + assertFalse(stage1Inserts.get(2) instanceof Replacement); assertEquals(new EntityID(1), stage1Inserts.get(2).getId()); - assertFalse(stage1Inserts.get(2).hasReplacement()); assertEquals(null, stage1Inserts.get(2).getValue()); - assertEquals(Role.Property, stage1Inserts.get(3).getRole()); + assertFalse(stage1Inserts.get(3) instanceof Replacement); assertEquals(new EntityID(1), stage1Inserts.get(3).getId()); - assertFalse(stage1Inserts.get(3).hasReplacement()); assertEquals(null, stage1Inserts.get(3).getValue()); - deriveStage2Inserts(stage2Inserts, stage1Inserts); - assertEquals(1, stage2Inserts.size()); - assertEquals(Role.Property, stage2Inserts.get(0).getRole()); assertEquals(new EntityID(2), stage2Inserts.get(0).getId()); assertEquals("V1", ((SingleValue) stage2Inserts.get(0).getValue()).toDatabaseString()); - assertFalse(stage2Inserts.get(0).hasReplacement()); + assertEquals(new EntityID(-1), stage2Inserts.get(0).getDomain()); } /** @@ -366,32 +349,31 @@ public class InsertTest { p3.setStatementStatus(StatementStatus.FIX); r.addProperty(p3); - final LinkedList<EntityInterface> stage1Inserts = new LinkedList<EntityInterface>(); - final LinkedList<EntityInterface> stage2Inserts = new LinkedList<EntityInterface>(); + final LinkedList<Property> stage1Inserts = new LinkedList<>(); + final LinkedList<Property> stage2Inserts = new LinkedList<>(); - deriveStage1Inserts(stage1Inserts, r); + int count = deriveStage1Inserts(stage1Inserts, r); + deriveStage2Inserts(stage2Inserts, stage1Inserts, registerReplacementIds(count), r); assertEquals(4, stage1Inserts.size()); - assertEquals(Role.Property, stage1Inserts.get(0).getRole()); + + assertFalse(stage1Inserts.get(0) instanceof Replacement); assertEquals(new EntityID(1), stage1Inserts.get(0).getId()); assertFalse(stage1Inserts.get(0).hasReplacement()); assertEquals("V1", ((SingleValue) stage1Inserts.get(0).getValue()).toDatabaseString()); - assertEquals(Role.Property, stage1Inserts.get(1).getRole()); + assertTrue(stage1Inserts.get(1) instanceof Replacement); assertEquals(new EntityID(2), stage1Inserts.get(1).getId()); - assertTrue(stage1Inserts.get(1).hasReplacement()); - assertEquals(stage1Inserts.get(2), stage1Inserts.get(1).getReplacement()); assertTrue(stage1Inserts.get(1).getValue() instanceof CollectionValue); - assertEquals(Role.Domain, stage1Inserts.get(2).getRole()); - assertFalse(stage1Inserts.get(2).hasReplacement()); - assertTrue(stage1Inserts.get(2).getValue() instanceof CollectionValue); + assertFalse(stage1Inserts.get(2) instanceof Replacement); + assertEquals(new EntityID(-1), stage1Inserts.get(2).getId()); + assertEquals(2, ((ReferenceValue) stage1Inserts.get(2).getValue()).getId().toInteger()); - assertEquals(Role.Property, stage1Inserts.get(3).getRole()); + assertFalse(stage1Inserts.get(3) instanceof Replacement); assertEquals(new EntityID(3), stage1Inserts.get(3).getId()); - assertFalse(stage1Inserts.get(3).hasReplacement()); assertEquals("V3", ((SingleValue) stage1Inserts.get(3).getValue()).toDatabaseString()); - deriveStage2Inserts(stage2Inserts, stage1Inserts); + assertEquals(0, stage2Inserts.size()); } } diff --git a/src/test/java/org/caosdb/server/database/InsertTest2.java b/src/test/java/org/caosdb/server/database/InsertTest2.java new file mode 100644 index 0000000000000000000000000000000000000000..58cc58503dbef7e8ee1c300d67888f4d2ff37a7a --- /dev/null +++ b/src/test/java/org/caosdb/server/database/InsertTest2.java @@ -0,0 +1,148 @@ +package org.caosdb.server.database; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; +import org.caosdb.server.entity.Entity; +import org.caosdb.server.entity.EntityID; +import org.caosdb.server.entity.InsertEntity; +import org.caosdb.server.entity.RetrieveEntity; +import org.caosdb.server.entity.Role; +import org.caosdb.server.entity.StatementStatus; +import org.caosdb.server.entity.wrapper.Property; +import org.junit.jupiter.api.Test; + +public class InsertTest2 { + + private Deque<EntityID> registerReplacementIds(int count) { + Deque<EntityID> replacementIds = new ArrayDeque<>(); + for (int i = 1; i < count + 1; i++) { + replacementIds.add(new EntityID(-i)); + } + return replacementIds; + } + + @Test + public void transformation5() { + final Entity r = new InsertEntity("Test", Role.RecordType); + final Property p1 = new Property(new RetrieveEntity(new EntityID(1))); + p1.setRole("Property"); + p1.setDatatype("TEXT"); + p1.setDescription("desc1"); + p1.setDescOverride(true); + p1.setName("P1"); + p1.setNameOverride(true); + p1.setStatementStatus(StatementStatus.RECOMMENDED); + r.addProperty(p1); + + final Property p2 = new Property(new RetrieveEntity(new EntityID(2))); + p2.setRole("Property"); + p2.setDatatype("TEXT"); + p2.setDescription("desc2"); + p2.setDescOverride(true); + p2.setName("P2"); + p2.setNameOverride(true); + p2.setStatementStatus(StatementStatus.RECOMMENDED); + r.addProperty(p2); + + final Property p21 = new Property(new RetrieveEntity(new EntityID(1))); + p21.setRole("Property"); + p21.setDatatype("TEXT"); + p21.setDescription("desc21"); + p21.setDescOverride(true); + p21.setName("P21"); + p21.setNameOverride(true); + p21.setStatementStatus(StatementStatus.RECOMMENDED); + p2.addProperty(p21); + + final Property p22 = new Property(new RetrieveEntity(new EntityID(2))); + p22.setRole("Property"); + p22.setDatatype("TEXT"); + p22.setDescription("desc22"); + p22.setDescOverride(true); + p22.setName("P22"); + p22.setNameOverride(true); + p22.setStatementStatus(StatementStatus.RECOMMENDED); + p2.addProperty(p22); + + final Property p3 = new Property(new RetrieveEntity(new EntityID(3))); + p3.setRole("Property"); + p3.setDatatype("TEXT"); + p3.setDescription("desc3"); + p3.setDescOverride(true); + p3.setName("P3"); + p3.setNameOverride(true); + p3.setStatementStatus(StatementStatus.RECOMMENDED); + r.addProperty(p3); + + final Property p31 = new Property(new RetrieveEntity(new EntityID(1))); + p31.setRole("Property"); + p31.setDatatype("TEXT"); + p31.setDescription("desc31"); + p31.setDescOverride(true); + p31.setName("P31"); + p31.setNameOverride(true); + p31.setStatementStatus(StatementStatus.RECOMMENDED); + p3.addProperty(p31); + + final Property p32 = new Property(new RetrieveEntity(new EntityID(2))); + p32.setRole("Property"); + p32.setDatatype("TEXT"); + p32.setDescription("desc32"); + p32.setDescOverride(true); + p32.setName("P32"); + p32.setNameOverride(true); + p32.setStatementStatus(StatementStatus.RECOMMENDED); + p3.addProperty(p32); + + final Property p321 = new Property(new RetrieveEntity(new EntityID(1))); + p321.setRole("Property"); + p321.setDatatype("TEXT"); + p321.setDescription("desc321"); + p321.setDescOverride(true); + p321.setName("P321"); + p321.setNameOverride(true); + p321.setStatementStatus(StatementStatus.RECOMMENDED); + p32.addProperty(p321); + + final Property p322 = new Property(new RetrieveEntity(new EntityID(2))); + p322.setRole("Property"); + p322.setDatatype("TEXT"); + p322.setDescription("desc322"); + p322.setDescOverride(true); + p322.setName("P322"); + p322.setNameOverride(true); + p322.setStatementStatus(StatementStatus.RECOMMENDED); + p32.addProperty(p322); + + final Property p323 = new Property(new RetrieveEntity(new EntityID(3))); + p323.setRole("Property"); + p323.setDatatype("TEXT"); + p323.setDescription("desc323"); + p323.setDescOverride(true); + p323.setName("P323"); + p323.setNameOverride(true); + p323.setStatementStatus(StatementStatus.RECOMMENDED); + p32.addProperty(p323); + + final Property p33 = new Property(new RetrieveEntity(new EntityID(3))); + p33.setRole("Property"); + p33.setDatatype("TEXT"); + p33.setDescription("desc33"); + p33.setDescOverride(true); + p33.setName("P33"); + p33.setNameOverride(true); + p33.setStatementStatus(StatementStatus.RECOMMENDED); + p3.addProperty(p33); + + List<Property> stage1Inserts = new LinkedList<>(); + List<Property> stage2Inserts = new LinkedList<>(); + int c = DatabaseUtils.deriveStage1Inserts(stage1Inserts, r); + DatabaseUtils.deriveStage2Inserts(stage2Inserts, stage1Inserts, registerReplacementIds(c), r); + assertEquals(7, stage1Inserts.size()); + assertEquals(8, stage2Inserts.size()); + } +}