Skip to content

Commit

Permalink
Replaced ID concept with primary key concept
Browse files Browse the repository at this point in the history
  • Loading branch information
hylkevds committed Mar 15, 2024
1 parent ebadfe6 commit 74fb618
Show file tree
Hide file tree
Showing 106 changed files with 1,544 additions and 1,228 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
import de.fraunhofer.iosb.ilt.frostserver.model.core.Entity;
import de.fraunhofer.iosb.ilt.frostserver.model.core.EntitySet;
import de.fraunhofer.iosb.ilt.frostserver.model.core.EntitySetImpl;
import de.fraunhofer.iosb.ilt.frostserver.model.core.Id;
import de.fraunhofer.iosb.ilt.frostserver.model.core.PkValue;
import de.fraunhofer.iosb.ilt.frostserver.model.core.PrimaryKey;
import de.fraunhofer.iosb.ilt.frostserver.path.UrlHelper;
import de.fraunhofer.iosb.ilt.frostserver.property.EntityPropertyMain;
import de.fraunhofer.iosb.ilt.frostserver.property.NavigationPropertyMain;
Expand Down Expand Up @@ -58,20 +59,61 @@ public DefaultEntity(EntityType entityType) {
this.entityType = entityType;
}

public DefaultEntity(EntityType entityType, Id id) {
public DefaultEntity(EntityType entityType, PkValue pkValue) {
this.entityType = entityType;
setId(id);
setPrimaryKeyValues(pkValue);
}

/**
* Get the primary key definition of the (EntityType of the) Entity. This is
* a shorthand for getEntityType().getPrimaryKey();
*
* @return The primary key definition of the Entity.
*/
@Override
public final Id getId() {
return getProperty(entityType.getPrimaryKey());
public final PrimaryKey getPrimaryKey() {
return entityType.getPrimaryKey();
}

/**
* Key the values of the primary key fields for this Entity.
*
* @return the primary key values.
*/
@Override
public final DefaultEntity setId(Id id) {
entityProperties.put(entityType.getPrimaryKey(), id);
setProperties.add(entityType.getPrimaryKey());
public final PkValue getPrimaryKeyValues() {
List<EntityPropertyMain> keyProperties = entityType.getPrimaryKey().getKeyProperties();
PkValue pkValue = new PkValue(keyProperties.size());
int idx = 0;
for (EntityPropertyMain keyProperty : keyProperties) {
pkValue.set(idx, getProperty(keyProperty));
idx++;
}
return pkValue;
}

@Override
public boolean primaryKeyFullySet() {
List<EntityPropertyMain> keyProperties = entityType.getPrimaryKey().getKeyProperties();
for (EntityPropertyMain keyProperty : keyProperties) {
Object value = getProperty(keyProperty);
if (value == null) {
return false;
}
}
return true;
}

@Override
public final DefaultEntity setPrimaryKeyValues(PkValue values) {
int idx = 0;
for (EntityPropertyMain keyProperty : entityType.getPrimaryKey().getKeyProperties()) {
if (idx >= values.size()) {
throw new IllegalArgumentException("No value given for keyProperty " + idx);
}
setProperty(keyProperty, values.get(idx));
idx++;
}
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ public Query getQueryFor(EntityType entityType) {
}
for (NavigationPropertyMain np : entityType.getNavigationEntities()) {
Query subQuery = new Query(t.getModelRegistry(), queryDefaults, new ResourcePath("", Version.V_1_0, "/" + np.getName()), INTERNAL_ADMIN_PRINCIPAL)
.addSelect(np.getEntityType().getPrimaryKey())
.addSelect(np.getEntityType().getPrimaryKey().getKeyProperties())
.setMetadata(Metadata.INTERNAL_COMPARE);
query.addExpand(new Expand(t.getModelRegistry(), np).setSubQuery(subQuery));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
*/
package de.fraunhofer.iosb.ilt.frostserver.model;

import static de.fraunhofer.iosb.ilt.frostserver.util.Constants.NOT_IMPLEMENTED_MULTI_VALUE_PK;

import de.fraunhofer.iosb.ilt.frostserver.model.core.Entity;
import de.fraunhofer.iosb.ilt.frostserver.model.core.EntitySet;
import de.fraunhofer.iosb.ilt.frostserver.model.core.EntityValidator;
import de.fraunhofer.iosb.ilt.frostserver.model.core.Id;
import de.fraunhofer.iosb.ilt.frostserver.model.core.IdLong;
import de.fraunhofer.iosb.ilt.frostserver.model.core.IdString;
import de.fraunhofer.iosb.ilt.frostserver.model.core.IdUuid;
import de.fraunhofer.iosb.ilt.frostserver.model.core.PkSingle;
import de.fraunhofer.iosb.ilt.frostserver.model.core.PkValue;
import de.fraunhofer.iosb.ilt.frostserver.model.core.PrimaryKey;
import de.fraunhofer.iosb.ilt.frostserver.model.core.annotations.Annotatable;
import de.fraunhofer.iosb.ilt.frostserver.model.core.annotations.Annotation;
import de.fraunhofer.iosb.ilt.frostserver.path.PathElement;
Expand All @@ -46,7 +47,7 @@
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import org.apache.commons.lang3.NotImplementedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -83,7 +84,7 @@ public class EntityType implements Annotatable, Comparable<EntityType> {
/**
* The Property that is the primary key of the entity.
*/
private EntityPropertyMain primaryKey;
private PrimaryKey primaryKey;
/**
* The Set of PROPERTIES that Entities of this type have.
*/
Expand Down Expand Up @@ -141,13 +142,12 @@ public EntityType(String singular, String plural, boolean adminOnly) {
public EntityType registerProperty(Property property) {
properties.add(property);
propertiesByName.put(property.getName(), property);
if (property instanceof EntityPropertyMain) {
EntityPropertyMain<?> propertyMain = (EntityPropertyMain<?>) property;
for (String alias : propertyMain.getAliases()) {
if (property instanceof EntityPropertyMain<?> epm) {
for (String alias : epm.getAliases()) {
propertiesByName.put(alias, property);
}
if (primaryKey == null) {
primaryKey = propertyMain;
primaryKey = new PkSingle(epm);
}
}
return this;
Expand Down Expand Up @@ -196,15 +196,19 @@ public void init() {
}
}
// Make sure we have a default orderby and that it contains the primary key last.
boolean pkOrder = false;
final String pkName = primaryKey.getName();
for (OrderBy order : orderbyDefaults) {
if (pkName.equals(order.getExpression().toUrl())) {
pkOrder = true;
int pkCount = 0;
for (var keyProp : primaryKey.getKeyProperties()) {
String pkName = keyProp.getName();
for (OrderBy order : orderbyDefaults) {
if (pkName.equals(order.getExpression().toUrl())) {
pkCount++;
}
}
}
if (!pkOrder) {
orderbyDefaults.add(new OrderBy(new Path(primaryKey), OrderBy.OrderType.ASCENDING));
if (pkCount < primaryKey.getKeyProperties().size()) {
for (var keyProp : primaryKey.getKeyProperties()) {
orderbyDefaults.add(new OrderBy(new Path(keyProp), OrderBy.OrderType.ASCENDING));
}
}
}

Expand Down Expand Up @@ -276,7 +280,7 @@ public EntityValidator removeUpdateValidator(String name) {
return validatorsUpdateEntity.remove(name);
}

public EntityPropertyMain<Id> getPrimaryKey() {
public PrimaryKey getPrimaryKey() {
return primaryKey;
}

Expand Down Expand Up @@ -407,28 +411,28 @@ public void setParent(PathElementEntitySet containingSet, Entity entity) throws
throw new IllegalArgumentException("Set does not have a parent entity!");
}
if (parent instanceof PathElementEntity parentEntity) {
Id parentId = parentEntity.getId();
if (parentId == null) {
if (!parentEntity.primaryKeyFullySet()) {
return;
}
setParent(entity, containingSet.getNavigationProperty().getInverse(), parentId);
PkValue parentKeyValues = parentEntity.getPkValues();
setParent(entity, containingSet.getNavigationProperty().getInverse(), parentKeyValues);
}
}

private void setParent(Entity entity, NavigationPropertyMain navPropToParent, Id parentId) throws IncompleteEntityException {
private void setParent(Entity entity, NavigationPropertyMain navPropToParent, PkValue parentPkValues) throws IncompleteEntityException {
if (navPropToParent == null) {
LOGGER.error("Incorrect 'parent' entity type for {}: {}", entityName, navPropToParent);
throw new IncompleteEntityException("Incorrect 'parent' entity type for " + entityName + ": " + navPropToParent);
}
EntityType parentType = navPropToParent.getEntityType();
if (navPropToParent instanceof NavigationPropertyEntitySet navPropToParentSet) {
entity.addNavigationEntity(navPropToParentSet, new DefaultEntity(parentType).setId(parentId));
entity.addNavigationEntity(navPropToParentSet, new DefaultEntity(parentType).setPrimaryKeyValues(parentPkValues));
} else if (navPropToParent instanceof NavigationPropertyEntity navPropToParentEntity) {
Entity parent = entity.getProperty(navPropToParentEntity);
if (parent != null && !parentId.equals(parent.getId())) {
if (parent != null && !Objects.equals(parentPkValues, parent.getPrimaryKeyValues())) {
throw new IllegalArgumentException("Navigation property " + navPropToParent.getName() + " set in both JSON and URL.");
}
entity.setProperty(navPropToParent, new DefaultEntity(parentType).setId(parentId));
entity.setProperty(navPropToParent, new DefaultEntity(parentType).setPrimaryKeyValues(parentPkValues));
} else {
throw new IllegalStateException("Unknown navigation property type: " + navPropToParent);
}
Expand Down Expand Up @@ -522,18 +526,14 @@ public int hashCode() {
return hash;
}

public Id parsePrimaryKey(String input) {
Object rawId = primaryKey.getType().parseFromUrl(input);
if (rawId instanceof UUID uuid) {
return new IdUuid(uuid);
}
if (rawId instanceof Number number) {
return new IdLong(number.longValue());
}
if (rawId instanceof CharSequence) {
return new IdString(rawId.toString());
public PkValue parsePrimaryKey(String input) {
if (primaryKey instanceof PkSingle pks) {
EntityPropertyMain keyProp = pks.getKeyProperties().get(0);
return new PkValue(1)
.set(0, keyProp.getType().parseFromUrl(input));
} else {
throw new NotImplementedException(NOT_IMPLEMENTED_MULTI_VALUE_PK);
}
throw new IllegalArgumentException("Can not use " + ((rawId == null) ? "null" : rawId.getClass().getName()) + " (" + input + ") as an Id");
}

public List<OrderBy> getOrderbyDefaults() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,24 @@
*/
public interface Entity extends NavigableElement {

public Id getId();
/**
* Get the primary key definition of the (EntityType of the) Entity. This is
* a shorthand for getEntityType().getPrimaryKey();
*
* @return The primary key definition of the Entity.
*/
public PrimaryKey getPrimaryKey();

/**
* Key the values of the primary key fields for this Entity.
*
* @return the primary key values.
*/
public PkValue getPrimaryKeyValues();

public boolean primaryKeyFullySet();

public Entity setId(Id id);
public Entity setPrimaryKeyValues(PkValue values);

/**
* @return self link. Might be null.
Expand Down Expand Up @@ -193,7 +208,7 @@ public default void validateUpdate() throws IncompleteEntityException {
public default ResourcePath getPath() {
EntityType type = getEntityType();
PathElementEntity epe = new PathElementEntity(type, null);
epe.setId(getId());
epe.setPkValues(getPrimaryKeyValues());
ResourcePath resourcePath = new ResourcePath();
resourcePath.addPathElement(epe, true, false);
return resourcePath;
Expand Down

This file was deleted.

Loading

0 comments on commit 74fb618

Please sign in to comment.