Skip to content
Snippets Groups Projects
Commit 82ea73aa authored by Timm Fitschen's avatar Timm Fitschen
Browse files

Merge branch 'f-inheritance' into 'dev'

Bug: Inheritance job cannot handle inheritance from same container

See merge request caosdb/caosdb-server!54
parents 9c4d53dc 9bebcb64
No related branches found
No related tags found
No related merge requests found
......@@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Inheritance job cannot handle inheritance from same container (!54)
* Bug in the query parser (MR!56) - The parser would throw an error when the
query contains a conjunction or disjunction filter with a first element which
is another disjunction or conjunction and being wrapped into parenthesis.
......
......@@ -22,12 +22,21 @@
*/
package org.caosdb.server.entity;
/**
* The statement status has two purposes.
*
* <p>1. Storing the importance of an entity (any of OBLIGATORY, RECOMMENDED, SUGGESTED, or FIX). 2.
* Marking an entity as a REPLACEMENT which is needed for flat representation of deeply nested
* properties. This constant is only used for internal processes and has no meaning in the API. That
* is also the reason why this enum is not called "Importance". Apart from that, in most cases its
* meaning is identical to the importance of an entity.
*
* @author Timm Fitschen (t.fitschen@indiscale.com)
*/
public enum StatementStatus {
OBLIGATORY,
RECOMMENDED,
SUGGESTED,
FIX,
SUBTYPING,
INHERITANCE,
REPLACEMENT
}
......@@ -23,26 +23,36 @@
package org.caosdb.server.jobs.core;
import java.util.ArrayList;
import java.util.List;
import org.caosdb.server.database.backend.transaction.RetrieveFullEntity;
import org.caosdb.server.entity.Entity;
import org.caosdb.server.entity.EntityInterface;
import org.caosdb.server.entity.Message;
import org.caosdb.server.entity.Message.MessageType;
import org.caosdb.server.entity.StatementStatus;
import org.caosdb.server.entity.wrapper.Property;
import org.caosdb.server.jobs.EntityJob;
import org.caosdb.server.transaction.Insert;
import org.caosdb.server.transaction.Update;
import org.caosdb.server.utils.EntityStatus;
/**
* Add all those properties from the parent to the child which have the same importance (or higher).
*
* @author Timm Fitschen (t.fitschen@indiscale.com)
*/
public class Inheritance extends EntityJob {
/*
* Storing which properties of the properties of the parents should be inherited by the child.
*/
public enum INHERITANCE_MODE {
NONE,
ALL,
OBLIGATORY,
FIX,
RECOMMENDED,
DONE
NONE, // inherit no properties from this parent
ALL, // inherit all inheritable properties, alias for suggested
OBLIGATORY, // inherit only obligatory properties
RECOMMENDED, // inherit obligatory and recommended properties
SUGGESTED, // inherit all inheritable properties, alias for all
FIX, // inherit fix properties only (deprecated)
};
public static final Message ILLEGAL_INHERITANCE_MODE =
......@@ -66,51 +76,22 @@ public class Inheritance extends EntityJob {
INHERITANCE_MODE.valueOf(parent.getFlags().get("inheritance").toUpperCase());
// mark inheritance flag as done
parent.setFlag("inheritance", "done");
if (inheritance == INHERITANCE_MODE.NONE || inheritance == INHERITANCE_MODE.DONE) {
parent.setFlag("inheritance", null);
if (inheritance == INHERITANCE_MODE.NONE) {
break parentLoop;
}
runJobFromSchedule(getEntity(), CheckParValid.class);
execute(new RetrieveFullEntity(parent));
if (parent.hasProperties()) {
// loop over all properties of the parent and
// collect
// properties to be transfered
for (final EntityInterface parProperty : parent.getProperties()) {
switch (inheritance) {
case ALL:
transfer.add(parProperty);
break;
case RECOMMENDED:
if (parProperty
.getStatementStatus()
.toString()
.equalsIgnoreCase(INHERITANCE_MODE.RECOMMENDED.toString())) {
transfer.add(parProperty);
}
case OBLIGATORY:
if (parProperty
.getStatementStatus()
.toString()
.equalsIgnoreCase(INHERITANCE_MODE.OBLIGATORY.toString())) {
transfer.add(parProperty);
}
case FIX:
if (parProperty
.getStatementStatus()
.toString()
.equalsIgnoreCase(INHERITANCE_MODE.FIX.toString())) {
transfer.add(parProperty);
}
break;
default:
break;
}
}
// try to get the parent entity from the current transaction container
EntityInterface foreign = getEntityByName(parent.getName());
if (foreign == null) {
// was not in container -> retrieve from database.
execute(new RetrieveFullEntity(parent));
foreign = parent;
}
collectInheritedProperties(transfer, foreign, inheritance);
} catch (final IllegalArgumentException e) {
parent.addWarning(ILLEGAL_INHERITANCE_MODE);
break parentLoop;
......@@ -142,9 +123,10 @@ public class Inheritance extends EntityJob {
}
final INHERITANCE_MODE inheritance =
INHERITANCE_MODE.valueOf(property.getFlags().get("inheritance").toUpperCase());
// mark inheritance flag as done
property.setFlag("inheritance", "done");
if (inheritance == INHERITANCE_MODE.NONE || inheritance == INHERITANCE_MODE.DONE) {
property.setFlag("inheritance", null);
if (inheritance == INHERITANCE_MODE.NONE) {
break propertyLoop;
}
......@@ -164,48 +146,14 @@ public class Inheritance extends EntityJob {
} else {
execute(new RetrieveFullEntity(validProperty));
}
if (validProperty.getEntityStatus() == EntityStatus.VALID
&& validProperty.hasProperties()) {
// loop over all properties of the property and
// collect
// properties to be transfered
for (final EntityInterface propProperty : validProperty.getProperties()) {
switch (inheritance) {
case ALL:
transfer.add(propProperty);
break;
case RECOMMENDED:
if (propProperty
.getStatementStatus()
.toString()
.equalsIgnoreCase(INHERITANCE_MODE.RECOMMENDED.toString())) {
transfer.add(propProperty);
}
case OBLIGATORY:
if (propProperty
.getStatementStatus()
.toString()
.equalsIgnoreCase(INHERITANCE_MODE.OBLIGATORY.toString())) {
transfer.add(propProperty);
}
case FIX:
if (propProperty
.getStatementStatus()
.toString()
.equalsIgnoreCase(INHERITANCE_MODE.FIX.toString())) {
transfer.add(propProperty);
}
break;
default:
break;
}
}
if (validProperty.getEntityStatus() == EntityStatus.VALID) {
collectInheritedProperties(transfer, validProperty, inheritance);
}
} catch (final IllegalArgumentException e) {
property.addWarning(ILLEGAL_INHERITANCE_MODE);
break propertyLoop;
}
// transfer properties if they are not implemented yet
outerLoop:
for (final EntityInterface prop : transfer) {
......@@ -222,4 +170,52 @@ public class Inheritance extends EntityJob {
}
}
}
/**
* Put all those properties from the `from` entity into the `transfer` List which match the
* INHERITANCE_MODE.
*
* <p>That means:
*
* @param transfer
* @param from
* @param inheritance
*/
private void collectInheritedProperties(
List<EntityInterface> transfer, EntityInterface from, INHERITANCE_MODE inheritance) {
if (from.hasProperties()) {
for (final EntityInterface propProperty : from.getProperties()) {
switch (inheritance) {
// the following cases are ordered according to their importance level and use a
// fall-through.
case ALL:
case SUGGESTED:
if (propProperty.getStatementStatus() == StatementStatus.SUGGESTED) {
transfer.add(propProperty);
}
// fall-through!
case RECOMMENDED:
if (propProperty.getStatementStatus() == StatementStatus.RECOMMENDED) {
transfer.add(propProperty);
}
// fall-through!
case OBLIGATORY:
if (propProperty.getStatementStatus() == StatementStatus.OBLIGATORY) {
transfer.add(propProperty);
}
break;
case FIX:
if (propProperty.getStatementStatus() == StatementStatus.FIX) {
transfer.add(propProperty);
propProperty.addWarning(
new Message(
MessageType.Warning,
"DeprecationWarning: The inheritance of fix properties is deprecated and will be removed from the API in the near future. Clients have to copy fix properties by themselves, if necessary."));
}
default:
break;
}
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment