
uk.gov.gchq.gaffer.data.elementdefinition.ElementDefinitions Maven / Gradle / Ivy
/*
* Copyright 2016-2019 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package uk.gov.gchq.gaffer.data.elementdefinition;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import uk.gov.gchq.gaffer.commonutil.CloseableUtil;
import uk.gov.gchq.gaffer.commonutil.ToStringBuilder;
import uk.gov.gchq.gaffer.data.elementdefinition.exception.SchemaException;
import uk.gov.gchq.gaffer.exception.SerialisationException;
import uk.gov.gchq.gaffer.jsonserialisation.JSONSerialiser;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY;
/**
*
* Contains the full list of groups in the graph.
*
*
* This class must be JSON serialisable.
* A schema should normally be written in JSON and then deserialised at runtime.
* Examples of JSON schemas can be found in the example projects.
*
*
* @param the type of {@link ElementDefinition} for the entities
* @param the type of {@link ElementDefinition} for the edges
*/
public abstract class ElementDefinitions {
/**
* Map of edge type to edge definition.
*/
private Map edges;
/**
* Map of entity type to entity definition.
*/
private Map entities;
protected ElementDefinitions() {
edges = new HashMap<>();
entities = new HashMap<>();
}
public byte[] toJson(final boolean prettyPrint, final String... fieldsToExclude) throws SchemaException {
try {
return JSONSerialiser.serialise(this, prettyPrint, fieldsToExclude);
} catch (final SerialisationException e) {
throw new SchemaException(e.getMessage(), e);
}
}
/**
* Looks the group up in the entity definitions then if it doesn't find a definition it will look it up in the edge definitions.
* If you know the type of the element (Entity or Edge) then use getEntity or getEdge.
*
* @param group an group
* @return the {@link uk.gov.gchq.gaffer.data.elementdefinition.ElementDefinition} for the given group
*/
public ElementDefinition getElement(final String group) {
return isEntity(group) ? getEntity(group) : getEdge(group);
}
public EDGE_DEF getEdge(final String group) {
return edges.get(group);
}
public ENTITY_DEF getEntity(final String group) {
return entities.get(group);
}
public boolean isEntity(final String group) {
return entities.containsKey(group);
}
public boolean isEdge(final String group) {
return edges.containsKey(group);
}
@JsonIgnore
public Set getEdgeGroups() {
return null != edges ? edges.keySet() : Collections.emptySet();
}
@JsonIgnore
public Set getEntityGroups() {
return null != entities ? entities.keySet() : Collections.emptySet();
}
/**
* Returns a new hash set with all entity and edge groups.
*
* @return a new hash set with all entity and edge groups.
*/
@JsonIgnore
public Set getGroups() {
final Set entityGroups = getEntityGroups();
final Set edgeGroups = getEdgeGroups();
final Set groups = new HashSet<>(entityGroups.size() + edgeGroups.size());
groups.addAll(entityGroups);
groups.addAll(edgeGroups);
return groups;
}
@JsonIgnore
public boolean hasEntities() {
return null != entities && !entities.isEmpty();
}
@JsonIgnore
public boolean hasEdges() {
return null != edges && !edges.isEmpty();
}
@JsonIgnore
public boolean hasGroups() {
return hasEntities() || hasEdges();
}
@JsonInclude(NON_EMPTY)
public Map getEdges() {
return edges;
}
@JsonInclude(NON_EMPTY)
public Map getEntities() {
return entities;
}
protected void setEdges(final Map edges) {
this.edges = edges;
}
protected void setEntities(final Map entities) {
this.entities = entities;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (null == obj || getClass() != obj.getClass()) {
return false;
}
final ElementDefinitions, ?> that = (ElementDefinitions, ?>) obj;
return new EqualsBuilder()
.append(edges, that.edges)
.append(entities, that.entities)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(31, 5)
.append(edges)
.append(entities)
.toHashCode();
}
@Override
public String toString() {
return new ToStringBuilder(this)
.append("edges", edges)
.append("entities", entities)
.toString();
}
protected void lock() {
edges = Collections.unmodifiableMap(edges);
entities = Collections.unmodifiableMap(entities);
}
/**
* Builder for {@link uk.gov.gchq.gaffer.data.elementdefinition.ElementDefinitions}.
*
* @param the entity definition type.
* @param the entity definition type.
*/
@JsonPOJOBuilder(buildMethodName = "build", withPrefix = "set")
public abstract static class BaseBuilder, ENTITY_DEF extends ElementDefinition, EDGE_DEF extends ElementDefinition, CHILD_CLASS extends BaseBuilder> {
private ELEMENT_DEFS elementDefs;
protected BaseBuilder(final ELEMENT_DEFS elementDefs) {
this.elementDefs = elementDefs;
}
/**
* Adds an edge definition for a given edge type.
*
* @param group the edge type
* @param edgeDef the edge definition for the given edge type.
* @return this Builder
*/
public CHILD_CLASS edge(final String group, final EDGE_DEF edgeDef) {
elementDefs.getEdges().put(group, edgeDef);
return self();
}
@JsonSetter("edges")
public CHILD_CLASS edges(final Map edges) {
elementDefs.getEdges().clear();
return addEdges(edges);
}
public CHILD_CLASS addEdges(final Map edges) {
if (null != edges) {
elementDefs.getEdges().putAll(edges);
}
return self();
}
/**
* Adds an entity definition for a given entity type.
*
* @param group the entity type
* @param entityDef the entity definition for the given entity type.
* @return this Builder
*/
public CHILD_CLASS entity(final String group, final ENTITY_DEF entityDef) {
if (null == entityDef) {
throw new IllegalArgumentException("Entity definition is required");
}
elementDefs.getEntities().put(group, entityDef);
return self();
}
@JsonSetter("entities")
public CHILD_CLASS entities(final Map entities) {
elementDefs.getEntities().clear();
return addEntities(entities);
}
public CHILD_CLASS addEntities(final Map entities) {
if (null != entities) {
elementDefs.getEntities().putAll(entities);
}
return self();
}
public CHILD_CLASS removeEdges(final Predicate> filter) {
elementDefs.getEdges().entrySet().removeIf(filter);
return self();
}
public CHILD_CLASS removeEntities(final Predicate> filter) {
elementDefs.getEntities().entrySet().removeIf(filter);
return self();
}
public CHILD_CLASS json(final Class extends ELEMENT_DEFS> clazz, final Path... filePaths) throws SchemaException {
return json(clazz, (Object[]) filePaths);
}
public CHILD_CLASS json(final Class extends ELEMENT_DEFS> clazz, final InputStream... inputStreams) throws SchemaException {
try {
return json(clazz, (Object[]) inputStreams);
} finally {
if (null != inputStreams) {
for (final InputStream inputStream : inputStreams) {
CloseableUtil.close(inputStream);
}
}
}
}
public CHILD_CLASS json(final Class extends ELEMENT_DEFS> clazz, final byte[]... jsonBytes) throws SchemaException {
return json(clazz, (Object[]) jsonBytes);
}
public CHILD_CLASS json(final Class extends ELEMENT_DEFS> clazz, final Object[] jsonItems) throws SchemaException {
if (null != jsonItems) {
for (final Object jsonItem : jsonItems) {
try {
if (jsonItem instanceof InputStream) {
merge(JSONSerialiser.deserialise((InputStream) jsonItem, clazz));
} else if (jsonItem instanceof Path) {
final Path path = (Path) jsonItem;
if (Files.isDirectory(path)) {
for (final Path filePath : Files.newDirectoryStream(path)) {
merge(JSONSerialiser.deserialise(Files.readAllBytes(filePath), clazz));
}
} else {
merge(JSONSerialiser.deserialise(Files.readAllBytes(path), clazz));
}
} else {
merge(JSONSerialiser.deserialise((byte[]) jsonItem, clazz));
}
} catch (final IOException e) {
throw new SchemaException("Failed to load element definitions from bytes", e);
}
}
}
return self();
}
protected abstract CHILD_CLASS merge(final ELEMENT_DEFS newElementDefs);
/**
* Builds the {@link uk.gov.gchq.gaffer.data.elementdefinition.ElementDefinitions} validates it and returns it.
*
* @return the build {@link uk.gov.gchq.gaffer.data.elementdefinition.ElementDefinitions}.
*/
public ELEMENT_DEFS build() {
elementDefs.lock();
return elementDefs;
}
protected ELEMENT_DEFS getElementDefs() {
return elementDefs;
}
protected void setElementDefs(final ELEMENT_DEFS elementDefs) {
this.elementDefs = elementDefs;
}
protected abstract CHILD_CLASS self();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy