diff --git a/src/main/java/org/caosdb/server/database/DatabaseUtils.java b/src/main/java/org/caosdb/server/database/DatabaseUtils.java index 8f4a59bb1057aa7c9621a8e174295ee2264081d5..5799d23faf3435e9bb939666770aedd7a0a6c00b 100644 --- a/src/main/java/org/caosdb/server/database/DatabaseUtils.java +++ b/src/main/java/org/caosdb/server/database/DatabaseUtils.java @@ -40,9 +40,6 @@ import org.caosdb.server.database.proto.VerySparseEntity; import org.caosdb.server.datatype.AbstractCollectionDatatype; import org.caosdb.server.datatype.CollectionValue; import org.caosdb.server.datatype.GenericValue; -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.Message; @@ -55,6 +52,9 @@ import org.caosdb.server.entity.wrapper.Property; public class DatabaseUtils { + private static final String DELETED_REFERENCE_IN_PREVIOUS_VERSION = + "DELETED_REFERENCE_IN_PREVIOUS_VERSION"; + public static final String bytes2UTF8(final byte[] bytes) { if (bytes == null) { return null; @@ -265,100 +265,6 @@ public class DatabaseUtils { } } - private static void replace( - final Property p, final Map<EntityID, Property> domainMap, final boolean isHead) { - // ... find the corresponding domain and replace it - ReferenceValue ref; - try { - ref = ReferenceValue.parseReference(p.getValue()); - } catch (final Message e) { - throw new RuntimeException("This should never happen."); - } - final EntityInterface replacement = domainMap.get(ref.getId()); - if (replacement == null) { - if (isHead) { - throw new NullPointerException("Replacement was null"); - } - // entity has been deleted (we are processing properties of an old entity version) - p.setValue(null); - p.addWarning( - new Message( - "The referenced entity has been deleted in the mean time and is not longer available.")); - return; - } - if (replacement.isDescOverride()) { - p.setDescOverride(true); - p.setDescription(replacement.getDescription()); - } - if (replacement.isNameOverride()) { - p.setNameOverride(true); - p.setName(replacement.getName()); - } - if (replacement.isDatatypeOverride()) { - p.setDatatypeOverride(true); - p.setDatatype(replacement.getDatatype()); - } - p.setProperties(replacement.getProperties()); - p.setStatementStatus(replacement.getStatementStatus()); - p.setValue(replacement.getValue()); - } - - public static void transformToDeepPropertyTree( - final EntityInterface e, final List<Property> protoProperties) { - // here we will store every domain we can find and we will index it by - // its id. - final Map<EntityID, Property> domainMap = new HashMap<>(); - - // loop over all properties and collect the domains - for (final Property p : protoProperties) { - // if this is a domain it represents a deeper branch of the property - // tree. - if (p.getRole() == Role.Domain) { - if (domainMap.containsKey(p.getId())) { - // aggregate the multiple values. - final Property domain = domainMap.get(p.getId()); - if (!(domain.getValue() instanceof CollectionValue)) { - final SingleValue singleValue = (SingleValue) domain.getValue(); - final CollectionValue vals = new CollectionValue(); - final IndexedSingleValue iSingleValue = - new IndexedSingleValue(domain.getPIdx(), singleValue); - vals.add(iSingleValue); - domain.setValue(vals); - } - ((CollectionValue) domain.getValue()).add(p.getPIdx(), p.getValue()); - } else { - domainMap.put(p.getId(), p); - } - } - } - - // loop over all properties - final boolean isHead = - e.getVersion().getSuccessors() == null || e.getVersion().getSuccessors().isEmpty(); - for (final Property p : protoProperties) { - - // if this is a replacement - if (p.getStatementStatus() == StatementStatus.REPLACEMENT) { - replace(p, domainMap, isHead); - } - - for (final Property subP : p.getProperties()) { - if (subP.getStatementStatus() == StatementStatus.REPLACEMENT) { - replace(subP, domainMap, isHead); - } - } - - if (p.getId().equals(e.getId())) { - // this is the value of an abstract property. - e.setValue(p.getValue()); - } else if (p.getRole() != Role.Domain) { - // if this is not a domain it is to be added to the properties - // of e. - e.addProperty(p); - } - } - } - public static ArrayList<Property> parseFromProtoProperties( EntityInterface entity, List<ProtoProperty> protos) { final ArrayList<Property> ret = new ArrayList<Property>(); @@ -380,24 +286,23 @@ public class DatabaseUtils { } } else { + Message warning = null; + if (pp.status == DELETED_REFERENCE_IN_PREVIOUS_VERSION) { + pp.status = StatementStatus.FIX.name(); + warning = + new Message( + "The referenced entity has been deleted in the mean time and is not longer available."); + } final Property property = parseFlatProperty(pp); - // parseFromFlatProperties(property.getProperties(), pp.subProperties); + if (warning != null) { + property.addWarning(warning); + } ret.add(property); } } return ret; } - private static void parseFromFlatProperties( - final List<Property> properties, final List<ProtoProperty> props) { - if (props != null) - for (final ProtoProperty fp : props) { - final Property property = parseFlatProperty(fp); - parseFromFlatProperties(properties, fp.subProperties); - properties.add(property); - } - } - private static Property parseFlatProperty(final ProtoProperty fp) { final Property property = new Property(new RetrieveEntity()); property.parseProtoProperty(fp); @@ -406,7 +311,7 @@ public class DatabaseUtils { @SuppressWarnings("unchecked") public static LinkedList<ProtoProperty> transformToDeepPropertyTree( - List<ProtoProperty> properties) { + List<ProtoProperty> properties, boolean isHead) { LinkedList<ProtoProperty> result = new LinkedList<>(); Map<String, ProtoProperty> replacements = new HashMap<>(); for (ProtoProperty pp : properties) { @@ -436,7 +341,7 @@ public class DatabaseUtils { } for (ProtoProperty pp : properties) { if (pp.status.equals(StatementStatus.REPLACEMENT.toString())) { - replace(pp, replacements.get(pp.value)); + replace(pp, replacements.get(pp.value), isHead); } if (pp.collValues != null) { // sort @@ -455,16 +360,15 @@ public class DatabaseUtils { return result; } - private static void replace(ProtoProperty pp, ProtoProperty replacement) { + private static void replace(ProtoProperty pp, ProtoProperty replacement, boolean isHead) { if (replacement == null) { - throw new NullPointerException("Replacement was null"); - // // entity has been deleted (we are processing properties of an old entity version) - // p.setValue(null); - // p.addWarning( - // new Message( - // "The referenced entity has been deleted in the mean time and is not longer - // available.")); - // return; + if (isHead) { + throw new NullPointerException("Replacement was null"); + } + // entity has been deleted (we are processing properties of an old entity version) + pp.value = null; + pp.status = DELETED_REFERENCE_IN_PREVIOUS_VERSION; + return; } pp.desc = replacement.desc; pp.name = replacement.name; diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java index b0c5d5b7ba65054747d9d16c6cf82d6d29cc246e..c8843f9c919f64ed3af1df4f231549fb5282eeea 100644 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java +++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveProperties.java @@ -44,11 +44,10 @@ public class MySQLRetrieveProperties extends MySQLTransaction implements Retriev private static final String stmtStr = "call retrieveEntityProperties(?,?,?)"; private static final String stmtStr2 = "call retrieveOverrides(?,?,?)"; - private static final String isCollectionStmt = "call isCollection(?,?)"; @Override - public LinkedList<ProtoProperty> execute(final EntityID entity, final String version) - throws TransactionException { + public LinkedList<ProtoProperty> execute( + final EntityID entity, final String version, boolean isHead) throws TransactionException { try { final PreparedStatement prepareStatement = prepareStatement(stmtStr); @@ -60,7 +59,7 @@ public class MySQLRetrieveProperties extends MySQLTransaction implements Retriev p.subProperties = retrieveFlatPropertiesStage1(entity.toInteger(), p.id, version, prepareStatement); } - return DatabaseUtils.transformToDeepPropertyTree(propsStage1); + return DatabaseUtils.transformToDeepPropertyTree(propsStage1, isHead); } catch (final SQLException e) { throw new TransactionException(e); } catch (final ConnectionException e) { @@ -99,14 +98,12 @@ public class MySQLRetrieveProperties extends MySQLTransaction implements Retriev retrieveOverrides(domain, entity, version, retrieveOverrides, props); - PreparedStatement isCollectionStatement = prepareStatement(isCollectionStmt); - - return handleCollectionValues(props, isCollectionStatement); + return handleCollectionValues(props); } } - public List<ProtoProperty> handleCollectionValues( - List<FlatProperty> props, PreparedStatement isCollectionStatement) throws SQLException { + @Deprecated + public List<ProtoProperty> handleCollectionValues(List<FlatProperty> props) throws SQLException { List<ProtoProperty> result = new LinkedList<>(); for (FlatProperty fp : props) { diff --git a/src/main/java/org/caosdb/server/database/backend/interfaces/RetrievePropertiesImpl.java b/src/main/java/org/caosdb/server/database/backend/interfaces/RetrievePropertiesImpl.java index 69fc9e70e03e6060b639d757d97a26d796ee52b5..6bf2051ab1ada80bd09ca074b4b50b6af3abf574 100644 --- a/src/main/java/org/caosdb/server/database/backend/interfaces/RetrievePropertiesImpl.java +++ b/src/main/java/org/caosdb/server/database/backend/interfaces/RetrievePropertiesImpl.java @@ -29,5 +29,6 @@ import org.caosdb.server.entity.EntityID; public interface RetrievePropertiesImpl extends BackendTransactionImpl { - public LinkedList<ProtoProperty> execute(EntityID id, String version) throws TransactionException; + public LinkedList<ProtoProperty> execute(EntityID id, String version, boolean isHead) + throws TransactionException; } diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveProperties.java b/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveProperties.java index 5cd7ace12f8a1bbd73f1305a0a41f852df5c596e..caa4b6cf15161516abbff650c9677642271aafe9 100644 --- a/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveProperties.java +++ b/src/main/java/org/caosdb/server/database/backend/transaction/RetrieveProperties.java @@ -64,7 +64,8 @@ public class RetrieveProperties @Override public LinkedList<ProtoProperty> executeNoCache() throws TransactionException { final RetrievePropertiesImpl t = getImplementation(RetrievePropertiesImpl.class); - return t.execute(this.entity.getId(), this.entity.getVersion().getId()); + return t.execute( + this.entity.getId(), this.entity.getVersion().getId(), this.entity.getVersion().isHead()); } @Override