package cz.cvut.fel.adaptiverestfulapi.meta;
import cz.cvut.fel.adaptiverestfulapi.meta.model.*;
import org.slf4j.Logger;
import java.util.*;
/**
* Builder for model.
*/
public class ModelBuilder {
private final String name; // name of the model
private final Class baseClass;
private final Map<String, Entity> entities;
private final Map<String, Map<String, Attribute>> attributes;
private final Map<String, Map<String, Relationship>> relationships;
private final List<String> errors;
public ModelBuilder(String name, Class baseClass) {
this.name = name;
this.baseClass = baseClass;
this.entities = new HashMap<>();
this.attributes = new HashMap<>();
this.relationships = new HashMap<>();
this.errors = new LinkedList<>();
}
public Set<Entity> getEntities() {
return new HashSet<>(this.entities.values());
}
public String getName() {
return this.name;
}
public Class getBaseClass() {
return this.baseClass;
}
public void addEntity(Entity entity) {
if (entity != null) {
if (this.isValid(entity)) {
this.entities.put(entity.getName(), entity);
this.attributes.put(entity.getName(), new HashMap<String, Attribute>());
this.relationships.put(entity.getName(), new HashMap<String, Relationship>());
}
}
}
public void addProperty(Property property, Entity entity) {
if (property instanceof Attribute) {
this.addAttribute((Attribute)property, entity);
} else if (property instanceof Relationship) {
this.addRelationship((Relationship)property, entity);
}
}
protected void addAttribute(Attribute attribute, Entity entity) {
if (this.isValid(attribute, entity)) {
this.attributes.get(entity.getName()).put(attribute.getName(), attribute);
}
}
protected void addRelationship(Relationship relationship, Entity entity) {
if (this.isValid(relationship, entity)) {
this.relationships.get(entity.getName()).put(relationship.getName(), relationship);
}
}
protected boolean isValid(Entity entity) {
boolean valid = true;
if (entity.getName() == null || entity.getName().isEmpty()) {
this.addError("Entity name " + entity.getName() + " is not valid.");
valid = false;
}
if (entity.getEntityClass() == null) {
this.addError("Entity class " + entity.getEntityClass() + " is not valid.");
valid = false;
}
// TODO check for duplicates?
return valid;
}
protected boolean isValid(Attribute attribute, Entity entity) {
boolean valid = true;
valid = this.isValid(entity);
if (attribute.getName() == null || attribute.getName().isEmpty()) {
this.addError("Attribute name " + attribute.getName() + " is not valid on entity " + entity.getName() + ".");
valid = false;
}
// TODO check for duplicates?
return valid;
}
protected boolean isValid(Relationship relationship, Entity entity) {
boolean valid = true;
valid = this.isValid(entity);
if (relationship.getName() == null || relationship.getName().isEmpty()) {
this.addError("Relationship name " + relationship.getName() + " is not valid on entity " + entity.getName() + ".");
valid = false;
}
if (!this.entities.containsKey(relationship.getTargetEntity())) {
this.addError("Relationship " + relationship.getName() + " has invalid target entity named " + relationship.getTargetEntity());
valid = false;
}
// TODO check for duplicates?
return valid;
}
public boolean hasErrors() {
return !this.errors.isEmpty();
}
protected void addError(String error) {
this.errors.add(error);
}
public Model build(Logger logger) {
if (this.entities.size() == 0) {
this.addError("There are no entities in the model \"" + this.name + "\"");
}
if (this.hasErrors()) {
if (logger != null) {
for (String error : this.errors) {
logger.error(error);
}
}
return null;
}
Map<String, Entity> entities = new HashMap<>();
for (Entity entity : this.entities.values()) {
Entity e = new Entity(entity.getName(),
entity.getEntityClass(),
this.attributes.get(entity.getName()).values(),
this.relationships.get(entity.getName()).values());
entities.put(e.getName(), e);
}
return new Model(this.name, entities.values());
}
}