com.nhl.link.rest.runtime.constraints.EntityConstraintHandler Maven / Gradle / Ivy
package com.nhl.link.rest.runtime.constraints;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.nhl.link.rest.EntityConstraint;
import com.nhl.link.rest.EntityUpdate;
import com.nhl.link.rest.ResourceEntity;
import com.nhl.link.rest.annotation.ClientReadable;
import com.nhl.link.rest.annotation.ClientWritable;
import com.nhl.link.rest.meta.LrAttribute;
import com.nhl.link.rest.runtime.processor.update.UpdateContext;
/**
* @since 1.6
*/
class EntityConstraintHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(EntityConstraintHandler.class);
private EntityConstraintSource forRead;
private EntityConstraintSource forWrite;
EntityConstraintHandler(List defaultReadConstraints,
List defaultWriteConstraints) {
// note that explicit defaults override annotations
// annotation-based constraints will be compiled dynamically
ConcurrentMap readMap = new ConcurrentHashMap<>();
for (EntityConstraint c : defaultReadConstraints) {
readMap.put(c.getEntityName(), c);
}
ConcurrentMap writeMap = new ConcurrentHashMap<>();
for (EntityConstraint c : defaultWriteConstraints) {
writeMap.put(c.getEntityName(), c);
}
this.forRead = new EntityConstraintSource(readMap) {
@Override
protected AnnotationData processAnnotation(Class> type) {
ClientReadable a = type.getAnnotation(ClientReadable.class);
if (a == null) {
return null;
}
return new AnnotationData(a.id(), a.value());
}
};
this.forWrite = new EntityConstraintSource(writeMap) {
@Override
protected AnnotationData processAnnotation(Class> type) {
ClientWritable a = type.getAnnotation(ClientWritable.class);
if (a == null) {
return null;
}
return new AnnotationData(a.id(), a.value());
}
};
}
void constrainResponse(ResourceEntity> resourceEntity) {
constrainForRead(resourceEntity);
}
void constrainUpdate(UpdateContext> context) {
EntityConstraint c = forWrite.getOrCreate(context.getEntity().getLrEntity());
if (!c.allowsId()) {
context.setIdUpdatesDisallowed(true);
}
// updates are not hierarchical yet, so simply check attributes...
// TODO: updates may contain FKs ... need to handle that
if (!c.allowsAllAttributes()) {
for (EntityUpdate> u : context.getUpdates()) {
// exclude disallowed attributes
Iterator it = u.getValues().keySet().iterator();
while (it.hasNext()) {
String attr = it.next();
if (!c.allowsAttribute(attr)) {
// do not report default properties, as this wasn't a
// client's fault it go there..
if (!context.getEntity().isDefault(attr)) {
LOGGER.info("Attribute not allowed, removing: " + attr + " for id " + u.getId());
}
it.remove();
}
}
}
}
for (EntityUpdate> u : context.getUpdates()) {
Iterator it = u.getRelatedIds().keySet().iterator();
while (it.hasNext()) {
String relationship = it.next();
if (!c.allowsRelationship(relationship)) {
LOGGER.info("Relationship not allowed, removing: " + relationship + " for id " + u.getId());
it.remove();
}
}
}
}
void constrainForRead(ResourceEntity> entity) {
EntityConstraint c = forRead.getOrCreate(entity.getLrEntity());
if (!c.allowsId()) {
entity.excludeId();
}
if (!c.allowsAllAttributes()) {
Iterator ait = entity.getAttributes().values().iterator();
while (ait.hasNext()) {
String a = ait.next().getName();
if (!c.allowsAttribute(a)) {
// hack: do not report default properties, as this wasn't a
// client's fault it go there..
if (!entity.isDefault(a)) {
LOGGER.info("Attribute not allowed, removing: " + a);
}
ait.remove();
}
}
}
Iterator>> rit = entity.getChildren().entrySet().iterator();
while (rit.hasNext()) {
Entry> e = rit.next();
if (c.allowsRelationship(e.getKey())) {
constrainForRead(e.getValue());
} else {
// do not report default properties, as this wasn't a client's
// fault it go there..
if (!entity.isDefault(e.getKey())) {
LOGGER.info("Relationship not allowed, removing: " + e.getKey());
}
rit.remove();
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy