Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.umlg.runtime.collection.persistent.BaseCollection Maven / Gradle / Ivy
package org.umlg.runtime.collection.persistent;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.tinkerpop.gremlin.process.traversal.Order;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.structure.*;
import org.joda.time.DateTime;
import org.umlg.runtime.adaptor.TransactionThreadEntityVar;
import org.umlg.runtime.adaptor.TransactionThreadVar;
import org.umlg.runtime.adaptor.UMLG;
import org.umlg.runtime.adaptor.UmlgAdminGraph;
import org.umlg.runtime.collection.*;
import org.umlg.runtime.collection.ocl.BodyExpressionEvaluator;
import org.umlg.runtime.collection.ocl.BooleanExpressionEvaluator;
import org.umlg.runtime.collection.ocl.IterateExpressionAccumulator;
import org.umlg.runtime.collection.ocl.OclStdLibCollection;
import org.umlg.runtime.domain.*;
import org.umlg.runtime.domain.ocl.OclState;
import org.umlg.runtime.notification.ChangeHolder;
import org.umlg.runtime.notification.UmlgNotificationManager;
import org.umlg.runtime.types.Password;
import org.umlg.runtime.types.UmlgType;
import org.umlg.runtime.util.UmlgFormatter;
import java.lang.reflect.Method;
import java.util.*;
public abstract class BaseCollection implements UmlgCollection, UmlgRuntimeProperty, OclStdLibCollection {
protected Collection internalCollection;
protected OclStdLibCollection oclStdLibCollection;
protected boolean loaded = false;
// This is the owner of the collection
protected UmlgNode owner;
// This is the vertex of the owner of the collection
protected Vertex vertex;
//Created when an element is added to the collection.
//Used to store the id of an association class instance.
protected Edge edge;
protected Class> parentClass;
// //The internal map is used to store the vertex representing a primitive or an enumeration
// protected ListMultimap internalVertexMap = ArrayListMultimap.create();
protected UmlgRuntimeProperty umlgRuntimeProperty;
protected boolean ignoreInverse = false;
protected static final String IN_EDGE_SEQUENCE_ID = "inEdgeSequenceId";
protected static final String OUT_EDGE_SEQUENCE_ID = "outEdgeSequenceId";
protected static final String LABEL_TO_FIRST_HYPER_VERTEX = "LTFHV";
protected static final String LABEL_TO_LAST_HYPER_VERTEX = "LTLHV";
protected static final String LABEL_TO_NEXT_HYPER_VERTEX = "LTNHV";
protected static final String LABEL_TO_ELEMENT_FROM_HYPER_VERTEX = "LTEFHV";
protected static final String LABEL_TO_FIRST_ELEMENT_IN_SEQUENCE = "LTFEIS";
protected static final String LABEL_TO_NEXT_IN_SEQUENCE = "LTNEIS";
protected static final String LABEL_TO_LAST_ELEMENT_IN_SEQUENCE = "LTLEIS";
//This is used to set the IN_EDGE_SEQUENCE_ID, OUT_EDGE_SEQUENCE_ID on the edge
protected int inverseCollectionSize;
public BaseCollection(UmlgRuntimeProperty runtimeProperty) {
this.umlgRuntimeProperty = runtimeProperty;
}
public BaseCollection(UmlgNode owner, UmlgRuntimeProperty runtimeProperty) {
super();
this.owner = owner;
this.vertex = owner.getVertex();
this.parentClass = owner.getClass();
this.umlgRuntimeProperty = runtimeProperty;
}
public BaseCollection(UmlgEnum owner, UmlgRuntimeProperty runtimeProperty) {
super();
this.parentClass = owner.getClass();
this.umlgRuntimeProperty = runtimeProperty;
}
protected void loadFromVertex() {
if (isManyPrimitive()) {
loadManyPrimitive();
} else if (isManyEnumeration()) {
loadManyEnumeration();
} else if (getDataTypeEnum() != null && (isManyToMany() || isOneToMany())) {
loadManyDataType();
} else if (isOnePrimitive()) {
loadOnePrimitive();
} else if (isOneEnumeration()) {
loadOneEnumeration();
} else if (getDataTypeEnum() != null && (isOneToOne() || isManyToOne())) {
loadOneDataType();
} else {
loadUmlgNodes();
}
this.loaded = true;
}
private void loadOnePrimitive() {
this.vertex.property(getPersistentName()).ifPresent(
value -> {
this.internalCollection.add(value);
}
);
}
private void loadOneEnumeration() {
this.vertex.property(getPersistentName()).ifPresent(
value -> {
Class> c = this.getPropertyType();
this.internalCollection.add((E) Enum.valueOf((Class extends Enum>) c, (String) value));
}
);
}
// protected Vertex removeFromInternalMap(Object key) {
// List vertexes = this.internalVertexMap.get(getPersistentName() + key.toString());
// Preconditions.checkState(vertexes.size() > 0, "BaseCollection.internalVertexMap must have a value for the key!");
// Vertex vertex = vertexes.get(0);
// this.internalVertexMap.remove(getPersistentName() + key.toString(), vertex);
// return vertex;
// }
// protected void putToInternalMap(Object key, Vertex vertex) {
// this.internalVertexMap.put(getPersistentName() + key.toString(), vertex);
// }
protected Iterator getEdges() {
if (this.isControllingSide()) {
return this.vertex.edges(Direction.OUT, this.getLabel());
} else {
return this.vertex.edges(Direction.IN, this.getLabel());
}
}
protected Iterator getEdges(Vertex v) {
if (!this.isControllingSide()) {
return v.edges(Direction.OUT, this.getLabel());
} else {
return v.edges(Direction.IN, this.getLabel());
}
}
protected Iterator getVertices() {
if (this.isControllingSide()) {
return UMLG.get().getUnderlyingGraph().traversal().V(this.vertex).out(this.getLabel());
} else {
return UMLG.get().getUnderlyingGraph().traversal().V(this.vertex).in(this.getLabel());
}
}
protected GraphTraversal> getVerticesWithEdge() {
if (this.isControllingSide()) {
//TODO gremlin/sqlg optimization needed, this is super inefficient now
return UMLG.get().getUnderlyingGraph().traversal().V(this.vertex)
.outE(this.getLabel())
.as("edge")
.order().by(BaseCollection.IN_EDGE_SEQUENCE_ID, Order.incr)
.inV()
.as("vertex")
.select();
} else {
return UMLG.get().getUnderlyingGraph().traversal().V(this.vertex)
.inE(this.getLabel())
.as("edge")
.order().by(BaseCollection.OUT_EDGE_SEQUENCE_ID, Order.incr)
.outV()
.as("vertex")
.select();
}
}
@Override
public boolean addAll(Collection extends E> c) {
maybeLoad();
boolean result = true;
for (E e : c) {
if (!this.add(e)) {
result = false;
}
}
return result;
}
/**
* This gets invoked from the opposite side in addInternal.
* It is called before the edge is created so the new element will not be loaded by loadFromVertex
*
* @param e the element to add
* @return true if the element was successfully added
*/
@Override
public boolean inverseAdder(E e) {
if (!this.loaded) {
loadFromVertex();
}
return this.internalCollection.add(e);
}
@Override
public boolean addIgnoreInverse(E e) {
this.ignoreInverse = true;
boolean result = add(e);
this.ignoreInverse = false;
return result;
}
@Override
public boolean add(E e) {
maybeLoad();
if (!this.ignoreInverse && (isQualified() || isInverseQualified())) {
validateQualifiedAssociation(e);
}
boolean result = this.internalCollection.add(e);
if (result) {
if (this.umlgRuntimeProperty.isChangeListener()) {
UmlgNotificationManager.INSTANCE.notify(
this.umlgRuntimeProperty,
ChangeHolder.of(
this.owner,
this.umlgRuntimeProperty,
ChangeHolder.ChangeType.ADD,
e
)
);
}
if (!(this.owner instanceof UmlgMetaNode)) {
TransactionThreadEntityVar.setNewEntity(this.owner);
}
//This is saved on the collection as the edge is needed on UmlgPropertyAssociationClassSet to set the id of the association class vertex
this.edge = addInternal(e);
// Edge can only be null on a one primitive
// if (this.edge == null && !isOnePrimitive() && !isOneEnumeration() && getDataTypeEnum() == null) {
// throw new IllegalStateException("Edge can only be null on isOne which is a String, Integer, Boolean or primitive");
// }
if (e instanceof UmlgNode && this.edge == null) {
throw new IllegalStateException("Edge can not be null for a UmlgNode");
}
if (isQualified() || isInverseQualified()) {
// Can only qualify TinkerNode's
if (!(e instanceof UmlgNode)) {
throw new IllegalStateException("Primitive properties can not be qualified!");
}
}
if (isOrdered()) {
addToLinkedList(this.edge);
}
if (isInverseOrdered()) {
// Can only qualify TinkerNode's
if (!(e instanceof UmlgNode)) {
throw new IllegalStateException("Primitive properties can not be qualified!");
}
addToInverseLinkedList(this.edge);
}
}
return result;
}
private void removeFromLinkedList(Vertex v) {
}
/**
* Find all hyper vertexes from vertexToRemove. There can be many as the list could have duplicates.
* Out of all the hyper vertexes find the earliest one in the list. To do that iterate to the beginning of the list looking to see which hyper vertex is before another.
*
* @param vertex
* @param direction
* @return
*/
private Vertex getFirstHyperVertexInListForVertex(Vertex vertex, Direction direction) {
Set hyperVertexes = new HashSet<>();
vertex.edges(Direction.IN, LABEL_TO_ELEMENT_FROM_HYPER_VERTEX).forEachRemaining(
e -> hyperVertexes.add(e.vertices(Direction.OUT).next())
);
//Take any hyper vertex and start iterating to the beginning.
Vertex firstHyperVertex = hyperVertexes.iterator().next();
hyperVertexes.remove(firstHyperVertex);
Iterator iterator = firstHyperVertex.edges(Direction.IN, LABEL_TO_NEXT_HYPER_VERTEX + direction);
while (iterator.hasNext()) {
Edge edge = iterator.next();
Vertex previousHyperVertex = edge.vertices(Direction.OUT).next();
if (hyperVertexes.contains(previousHyperVertex)) {
firstHyperVertex = previousHyperVertex;
iterator = firstHyperVertex.edges(Direction.IN, LABEL_TO_NEXT_HYPER_VERTEX + direction);
hyperVertexes.remove(previousHyperVertex);
} else {
iterator = previousHyperVertex.edges(Direction.IN, LABEL_TO_NEXT_HYPER_VERTEX + direction);
}
}
return firstHyperVertex;
}
private void removeFromInverseLinkedList(Vertex v) {
}
protected String getIdForLabel(Vertex vertexToRemove) {
return vertexToRemove.id().toString().replace(".", "_");
}
/**
* This must be implemented by the appropriate collection type
*
* @param edge
*/
protected abstract void addToLinkedList(Edge edge);
protected void addToInverseLinkedList(Edge edge) {
}
private void validateQualifiedAssociation(E e) {
if (!(e instanceof UmlgNode)) {
throw new IllegalStateException("Primitive properties can not be qualified!");
}
UmlgNode node = (UmlgNode) e;
if (isQualified()) {
List qualifiers = this.owner.getQualifiers(this.umlgRuntimeProperty, node, false);
validateQualifiedMultiplicity(false, this.vertex, qualifiers);
}
if (isInverseQualified()) {
List qualifiers = node.getQualifiers(this.umlgRuntimeProperty, this.owner, true);
validateQualifiedMultiplicity(true, node.getVertex(), qualifiers);
}
}
@Override
public boolean remove(Object o) {
maybeLoad();
boolean result = this.internalCollection.remove(o);
if (result) {
if (this.umlgRuntimeProperty.isChangeListener()) {
UmlgNotificationManager.INSTANCE.notify(
this.umlgRuntimeProperty,
ChangeHolder.of(
this.owner,
this.umlgRuntimeProperty,
ChangeHolder.ChangeType.REMOVE,
o
)
);
}
if (!(this.owner instanceof UmlgMetaNode)) {
TransactionThreadEntityVar.setNewEntity(this.owner);
}
@SuppressWarnings("unchecked")
E e = (E) o;
Vertex v;
if (o instanceof UmlgNode) {
UmlgNode node = (UmlgNode) o;
v = node.getVertex();
if (!(this.owner instanceof UmlgMetaNode)) {
TransactionThreadEntityVar.setNewEntity(node);
}
Set edges = UMLG.get().getEdgesBetween(this.vertex, v, this.getLabel());
for (Edge edge : edges) {
if (o instanceof TinkerAuditableNode) {
createAudit(e, true);
}
if (isOrdered()) {
removeFromLinkedList(((UmlgNode) o).getVertex());
}
if (isInverseOrdered()) {
removeFromInverseLinkedList(((UmlgNode) o).getVertex());
}
edge.remove();
//TODO optimize this to remove only the node, not initialize the collection
node.initialiseProperty(umlgRuntimeProperty, true);
//Need to break here for bag logic. There will only be more than one edge in the case of the collection being a bag.
break;
}
} else if ((isOneEnumeration() || isOnePrimitive()) && getDataTypeEnum() == null) {
this.vertex.property(getPersistentName()).remove();
if (isOnePrimitivePropertyOfAssociationClass()) {
//edgeId can be null when the property is set on association class that is not yet been added to its member ends.
Property edgeIdProperty = this.vertex.property(UmlgCollection.ASSOCIATION_CLASS_EDGE_ID);
if (edgeIdProperty.isPresent()) {
Edge edge1 = UMLG.get().traversal().E(edgeIdProperty.value()).next();
edge1.property(getPersistentName()).remove();
//This is here because Titan has the nasty habit of recreating edges and changing the id.
this.vertex.property(UmlgCollection.ASSOCIATION_CLASS_EDGE_ID, edge1.id().toString());
}
}
} else if (getDataTypeEnum() != null && (isManyToMany() || isOneToMany())) {
this.vertex.property(getPersistentName(), convertToArrayForRemoval());
// v = removeFromInternalMap(o.toString());
// if (isOrdered()) {
// removeFromLinkedList(v);
// }
// if (isInverseOrdered()) {
// removeFromInverseLinkedList(v);
// }
// v.remove();
} else if (getDataTypeEnum() != null) {
this.vertex.property(getPersistentName()).remove();
} else if (e.getClass().isEnum() && (isManyToMany() || isOneToMany())) {
this.vertex.property(getPersistentName(), convertToArrayForRemoval());
// v = removeFromInternalMap(o);
// if (isOrdered()) {
// removeFromLinkedList(v);
// }
// if (isInverseOrdered()) {
// removeFromInverseLinkedList(v);
// }
// v.remove();
} else {
this.vertex.property(getPersistentName(), convertToArrayForRemoval());
// v = removeFromInternalMap(o);
// if (this.owner instanceof TinkerAuditableNode) {
// createAudit(e, true);
// }
// if (isOrdered()) {
// removeFromLinkedList(v);
// }
// if (isInverseOrdered()) {
// removeFromInverseLinkedList(v);
// }
// v.remove();
}
}
return result;
}
protected Edge addInternal(E e) {
Vertex v = null;
validateElementType(e);
if (e instanceof UmlgNode) {
UmlgNode node = (UmlgNode) e;
if (!(this.owner instanceof UmlgMetaNode)) {
TransactionThreadEntityVar.setNewEntity(node);
}
v = node.getVertex();
if (this.isUnique() && (this.isOneToMany() || this.isOneToOne())) {
// Check that the existing one from the element does not exist,
// the user must first remove it
Iterator iteratorToOne = getEdges(v);
if (iteratorToOne.hasNext()) {
throw new IllegalStateException(String.format("Property %s has a multiplicity of 1 and is already set. First remove the value before setting it.", new String[]{getInverseQualifiedName()}));
}
}
if (!this.ignoreInverse) {
this.handleInverseSide(node, umlgRuntimeProperty, true, this.owner);
this.inverseCollectionSize = node.getSize(true, umlgRuntimeProperty);
}
} else if (isOnePrimitive()) {
this.vertex.property(getPersistentName(), e);
if (isOnePrimitivePropertyOfAssociationClass()) {
Property edgeIdProperty = this.vertex.property(UmlgCollection.ASSOCIATION_CLASS_EDGE_ID);
//edgeId can be null when the property is set on association class that is not yet been added to its member ends.
if (edgeIdProperty.isPresent()) {
UMLG.get().traversal().E(edgeIdProperty.value()).next().property(getPersistentName(), e);
}
}
} else if (isOneEnumeration()) {
this.vertex.property(getPersistentName(), ((Enum>) e).name());
if (isOnePrimitivePropertyOfAssociationClass()) {
//edgeId can be null when the property is set on association class that is not yet been added to its member ends.
Property edgeIdProperty = this.vertex.property(UmlgCollection.ASSOCIATION_CLASS_EDGE_ID);
if (edgeIdProperty.isPresent()) {
UMLG.get().traversal().E(edgeIdProperty.value()).next().property(getPersistentName(), ((Enum>) e).name());
}
}
// } else if (getDataTypeEnum() != null && (isManyToMany() || isOneToMany())) {
// v = UMLG.get().addVertex();
// v.property("className", e.getClass().getName());
// setDataTypeOnVertex(v, e);
// putToInternalMap(e, v);
} else if (getDataTypeEnum() != null && (isOneToOne() || isManyToOne())) {
setDataTypeOnVertex(this.vertex, e);
} else if (e.getClass().isEnum() && (isManyToMany() || isOneToMany())) {
this.vertex.property(getPersistentName(), convertToArray(e));
// v = UMLG.get().addVertex();
// v.property(getPersistentName(), ((Enum>) e).name());
// v.property("className", e.getClass().getName());
// putToInternalMap(e, v);
} else {
this.vertex.property(getPersistentName(), convertToArray(e));
// v = UMLG.get().addVertex();
// v.property(getPersistentName(), e);
// v.property("className", e.getClass().getName());
// putToInternalMap(e, v);
}
if (v != null) {
Edge edge = createEdge(e, v);
if (this.owner instanceof TinkerAuditableNode) {
createAudit(e, false);
}
if (e instanceof UmlgNode) {
((UmlgNode) e).setEdge(this.umlgRuntimeProperty, edge);
}
return edge;
} else {
if (owner instanceof TinkerAuditableNode) {
createPrimitiveAudit(e);
}
return null;
}
}
protected UmlgRuntimeProperty handleInverseSide(UmlgNode node, UmlgRuntimeProperty umlgRuntimeProperty, boolean b, UmlgNode owner) {
return node.inverseAdder(umlgRuntimeProperty, true, this.owner);
}
protected Edge createEdge(E e, Vertex v) {
Edge edge;
if (this.isControllingSide()) {
edge = this.vertex.addEdge(this.getLabel(), v);
if (this.isManyToMany()) {
edge.property("manyToManyCorrelationInverseTRUE", "SETTED");
}
} else {
edge = v.addEdge(this.getLabel(), this.vertex);
if (this.isManyToMany()) {
edge.property("manyToManyCorrelationInverseFALSE", "SETTED");
}
}
return edge;
}
private void createPrimitiveAudit(E e) {
TinkerAuditableNode auditOwner = (TinkerAuditableNode) owner;
if (TransactionThreadVar.hasNoAuditEntry(owner.getClass().getName() + owner.getUid())) {
auditOwner.createAuditVertex(false);
}
auditOwner.getAuditVertex().property(getLabel(), e);
}
protected void createAudit(E e, boolean deletion) {
if (!(owner instanceof TinkerAuditableNode)) {
throw new IllegalStateException("if the collection member is an TinkerAuditableNode, then the owner must be a TinkerAuditableNode!");
}
TinkerAuditableNode auditOwner = (TinkerAuditableNode) owner;
if (TransactionThreadVar.hasNoAuditEntry(owner.getClass().getName() + owner.getUid())) {
auditOwner.createAuditVertex(false);
}
if (e instanceof TinkerAuditableNode) {
TinkerAuditableNode node = (TinkerAuditableNode) e;
if (TransactionThreadVar.hasNoAuditEntry(node.getClass().getName() + node.getUid())) {
node.createAuditVertex(false);
}
Edge auditEdge;
if (isControllingSide()) {
auditEdge = auditOwner.getAuditVertex().addEdge(this.getLabel(), node.getAuditVertex());
auditEdge.property("outClass", auditOwner.getClass().getName() + "Audit");
auditEdge.property("inClass", node.getClass().getName() + "Audit");
} else {
auditEdge = node.getAuditVertex().addEdge(this.getLabel(), auditOwner.getAuditVertex());
auditEdge.property("inClass", auditOwner.getClass().getName() + "Audit");
auditEdge.property("outClass", node.getClass().getName() + "Audit");
}
if (deletion) {
auditEdge.property("deletedOn", UmlgFormatter.format(new DateTime()));
}
} else if (e.getClass().isEnum()) {
Vertex v = UMLG.get().addVertex();
v.property(getPersistentName(), ((Enum>) e).name());
Edge auditEdge = auditOwner.getAuditVertex().addEdge(this.getLabel(), v);
auditEdge.property("outClass", auditOwner.getClass().getName() + "Audit");
auditEdge.property("inClass", e.getClass().getName());
} else {
if (TransactionThreadVar.hasNoAuditEntry(owner.getClass().getName() + e.getClass().getName() + e.toString())) {
Vertex auditVertex = UMLG.get().addVertex();
auditVertex.property(getPersistentName(), e);
TransactionThreadVar.putAuditVertexFalse(owner.getClass().getName() + e.getClass().getName() + e.toString(), auditVertex);
auditVertex.property("transactionNo", ((UmlgAdminGraph) UMLG.get()).getTransactionCount());
Edge auditEdge;
if (isControllingSide()) {
auditEdge = auditOwner.getAuditVertex().addEdge(this.getLabel(), auditVertex);
auditEdge.property("outClass", this.parentClass.getName());
auditEdge.property("inClass", e.getClass().getName() + "Audit");
} else {
auditEdge = auditVertex.addEdge(this.getLabel(), auditOwner.getAuditVertex());
auditEdge.property("inClass", this.parentClass.getName());
auditEdge.property("outClass", e.getClass().getName() + "Audit");
}
if (deletion) {
auditEdge.property("transactionNo", ((UmlgAdminGraph) UMLG.get()).getTransactionCount());
auditEdge.property("deletedOn", UmlgFormatter.format(new DateTime()));
}
}
}
}
protected void maybeLoad() {
if (!this.loaded) {
loadFromVertex();
}
}
protected Vertex getVertexForDirection(Edge edge) {
if (this.isControllingSide()) {
return edge.vertices(Direction.IN).next();
} else {
return edge.vertices(Direction.OUT).next();
}
}
protected Class> getClassToInstantiate(Edge edge) {
try {
if (this.isControllingSide()) {
return Class.forName((String) edge.vertices(Direction.IN).next().value("className"));
} else {
return Class.forName((String) edge.vertices(Direction.OUT).next().value("className"));
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
protected Class> getClassToInstantiate(Vertex vertex) {
try {
if (this.isControllingSide()) {
return Class.forName((String) vertex.value("className"));
} else {
return Class.forName((String) vertex.value("className"));
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
protected Class> getClassToInstantiateFromHyperVertexEdge(Edge hyperVertexEdge) {
try {
final Vertex v = hyperVertexEdge.vertices(Direction.IN).next();
return Class.forName((String) v.value("className"));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
@Override
public int size() {
maybeLoad();
return this.internalCollection.size();
}
@Override
public boolean isEmpty() {
maybeLoad();
return this.internalCollection.isEmpty();
}
@Override
public boolean contains(Object o) {
maybeLoad();
return this.internalCollection.contains(o);
}
@Override
public Iterator iterator() {
maybeLoad();
return this.internalCollection.iterator();
}
@Override
public Object[] toArray() {
maybeLoad();
return this.internalCollection.toArray();
}
@Override
public T[] toArray(T[] a) {
maybeLoad();
return this.internalCollection.toArray(a);
}
@Override
public boolean containsAll(Collection> c) {
maybeLoad();
return this.internalCollection.containsAll(c);
}
@Override
public boolean retainAll(Collection> c) {
if (!this.loaded) {
loadFromVertex();
}
boolean result = true;
for (E e : this.internalCollection) {
if (!c.contains(e)) {
if (!this.remove(e)) {
result = false;
}
}
}
return result;
}
@Override
public boolean removeAll(Collection> c) {
maybeLoad();
boolean result = true;
for (Object object : c) {
if (!this.remove(object)) {
result = false;
}
}
return result;
}
private void validateQualifiedMultiplicity(boolean inverse, Vertex vertex, List qualifiers) {
if (qualifiers.get(0).isOne()) {
StringBuilder qualifierNames = new StringBuilder();
StringBuilder keys = new StringBuilder();
StringBuilder values = new StringBuilder();
long count = 1;
GraphTraversal traversal;
if (inverse) {
if (!isControllingSide()) {
traversal = UMLG.get().getUnderlyingGraph().traversal().V(vertex).out(this.getLabel());
} else {
traversal = UMLG.get().getUnderlyingGraph().traversal().V(vertex).in(this.getLabel());
}
} else {
if (!isControllingSide()) {
traversal = UMLG.get().getUnderlyingGraph().traversal().V(vertex).in(this.getLabel());
} else {
traversal = UMLG.get().getUnderlyingGraph().traversal().V(vertex).out(this.getLabel());
}
}
for (Qualifier qualifier : qualifiers) {
qualifierNames.append(qualifier.getUmlgRuntimeProperty().getQualifiedName());
qualifierNames.append(" ");
if (qualifier.getValue() == null) {
break;
}
keys.append(qualifier.getKey());
values.append(qualifier.getValue() == null ? "null" : qualifier.getValue().toString());
if (count++ < qualifiers.size()) {
keys.append(", ");
values.append(", ");
}
traversal.has(qualifier.getKey(), qualifier.getValue());
}
count = (Long) traversal.count().next();
if (count > 0) {
// Add info to exception
throw new IllegalStateException(
String.format(
"Qualifier %s fails, qualifier multiplicity is one and an entry for key '%s' and value '%s' already exist",
qualifierNames.toString(),
keys.toString(),
values.toString()));
}
}
}
@Override
public String toJson() {
maybeLoad();
StringBuilder sb = new StringBuilder();
if (isManyPrimitive() || isManyEnumeration()) {
sb.append("[");
int count = 0;
for (E e : this.internalCollection) {
count++;
if (e instanceof String) {
sb.append("\"");
sb.append(e);
sb.append("\"");
} else if (e instanceof UmlgEnum) {
sb.append("\"");
sb.append(e);
sb.append("\"");
} else {
sb.append(e);
}
if (count < size()) {
sb.append(",");
}
}
sb.append("]");
}
return sb.toString();
}
@Override
public boolean isAssociationClassProperty() {
return this.umlgRuntimeProperty.isAssociationClassProperty();
}
@Override
public boolean isOnePrimitivePropertyOfAssociationClass() {
return this.umlgRuntimeProperty.isOnePrimitivePropertyOfAssociationClass();
}
@Override
public boolean isOnePrimitive() {
return this.umlgRuntimeProperty.isOnePrimitive();
}
@Override
public DataTypeEnum getDataTypeEnum() {
return this.umlgRuntimeProperty.getDataTypeEnum();
}
@Override
public boolean isOneEnumeration() {
return this.umlgRuntimeProperty.isOneEnumeration();
}
@Override
public boolean isManyPrimitive() {
return this.umlgRuntimeProperty.isManyPrimitive();
}
@Override
public boolean isManyEnumeration() {
return this.umlgRuntimeProperty.isManyEnumeration();
}
@Override
public String getLabel() {
return this.umlgRuntimeProperty.getLabel();
}
@Override
public String getQualifiedName() {
return this.umlgRuntimeProperty.getQualifiedName();
}
@Override
public String getPersistentName() {
return this.umlgRuntimeProperty.getPersistentName();
}
@Override
public String getInverseQualifiedName() {
return this.umlgRuntimeProperty.getInverseQualifiedName();
}
@Override
public boolean isOneToOne() {
return this.umlgRuntimeProperty.isOneToOne();
}
@Override
public boolean isOneToMany() {
return this.umlgRuntimeProperty.isOneToMany();
}
@Override
public boolean isManyToOne() {
return this.umlgRuntimeProperty.isManyToOne();
}
@Override
public boolean isManyToMany() {
return this.umlgRuntimeProperty.isManyToMany();
}
@Override
public int getUpper() {
return this.umlgRuntimeProperty.getUpper();
}
@Override
public int getLower() {
return this.umlgRuntimeProperty.getLower();
}
@Override
public int getInverseUpper() {
return this.umlgRuntimeProperty.getInverseUpper();
}
@Override
public boolean isControllingSide() {
return this.umlgRuntimeProperty.isControllingSide();
}
@Override
public boolean isComposite() {
return this.umlgRuntimeProperty.isComposite();
}
@Override
public boolean isInverseComposite() {
return this.umlgRuntimeProperty.isInverseComposite();
}
@Override
public boolean isValid(int elementCount) {
return this.umlgRuntimeProperty.isValid(elementCount);
}
@Override
public boolean isQualified() {
return this.umlgRuntimeProperty.isQualified();
}
@Override
public boolean isInverseQualified() {
return this.umlgRuntimeProperty.isInverseQualified();
}
@Override
public boolean isOrdered() {
if (isManyPrimitive() || isManyEnumeration() || (getDataTypeEnum() != null && (isOneToMany() || isManyToMany()))) {
return false;
} else {
if (this.umlgRuntimeProperty.isOrdered() && this.umlgRuntimeProperty.isQualified() && getUpper() == 1) {
return true;
} else {
return this.umlgRuntimeProperty.isOrdered() && (getUpper() == -1 || getUpper() > 1);
}
}
}
@Override
public boolean isInverseOrdered() {
//primitives, enumerations and data types can not have a ordered inverse
if (isManyPrimitive() || isManyEnumeration() || (getDataTypeEnum() != null && (isOneToMany() || isManyToMany()))) {
return false;
} else {
if (this.umlgRuntimeProperty.isInverseOrdered() && this.umlgRuntimeProperty.isInverseQualified() && getUpper() == 1) {
return true;
} else {
return this.umlgRuntimeProperty.isInverseOrdered() && (getInverseUpper() == -1 || getInverseUpper() > 1);
}
}
}
@Override
public boolean isUnique() {
return this.umlgRuntimeProperty.isUnique();
}
@Override
public boolean isInverseUnique() {
return this.umlgRuntimeProperty.isInverseUnique();
}
@Override
public Class getPropertyType() {
return this.umlgRuntimeProperty.getPropertyType();
}
@Override
public boolean isChangeListener() {
return this.umlgRuntimeProperty.isChangeListener();
}
@Override
public boolean equals(UmlgCollection c) {
maybeLoad();
return this.oclStdLibCollection.equals(c);
}
@Override
public boolean notEquals(UmlgCollection c) {
maybeLoad();
return this.oclStdLibCollection.notEquals(c);
}
@Override
public E any(BooleanExpressionEvaluator v) {
maybeLoad();
return this.oclStdLibCollection.any(v);
}
@Override
public UmlgSet asSet() {
maybeLoad();
return this.oclStdLibCollection.asSet();
}
@Override
public UmlgOrderedSet asOrderedSet() {
maybeLoad();
return this.oclStdLibCollection.asOrderedSet();
}
@Override
public UmlgSequence asSequence() {
maybeLoad();
return this.oclStdLibCollection.asSequence();
}
@Override
public UmlgBag asBag() {
maybeLoad();
return this.oclStdLibCollection.asBag();
}
@Override
public R iterate(IterateExpressionAccumulator v) {
maybeLoad();
return this.oclStdLibCollection.iterate(v);
}
@Override
public boolean equals(Object object) {
maybeLoad();
return this.oclStdLibCollection.equals(object);
}
@Override
public boolean notEquals(Object object) {
maybeLoad();
return this.oclStdLibCollection.notEquals(object);
}
@Override
public Boolean oclIsNew() {
maybeLoad();
return this.oclStdLibCollection.oclIsNew();
}
@Override
public Boolean oclIsUndefined() {
maybeLoad();
return this.oclStdLibCollection.oclIsUndefined();
}
@Override
public Boolean oclIsInvalid() {
maybeLoad();
return this.oclStdLibCollection.oclIsInvalid();
}
@Override
public T oclAsType(T classifier) {
maybeLoad();
return this.oclStdLibCollection.oclAsType(classifier);
}
@Override
public Boolean oclIsTypeOf(Object object) {
maybeLoad();
return this.oclStdLibCollection.oclIsTypeOf(object);
}
@Override
public Boolean oclIsKindOf(Object object) {
maybeLoad();
return this.oclStdLibCollection.oclIsKindOf(object);
}
@Override
public Boolean oclIsInState(OclState state) {
maybeLoad();
return this.oclStdLibCollection.oclIsInState(state);
}
@Override
public Class oclType() {
maybeLoad();
return this.oclStdLibCollection.oclType();
}
@Override
public String oclLocale() {
maybeLoad();
return this.oclStdLibCollection.oclLocale();
}
@Override
public boolean includes(E t) {
maybeLoad();
return this.oclStdLibCollection.includes(t);
}
@Override
public boolean excludes(E t) {
maybeLoad();
return this.oclStdLibCollection.excludes(t);
}
@Override
public int count(E e) {
maybeLoad();
return this.oclStdLibCollection.count(e);
}
@Override
public Boolean includesAll(UmlgCollection c) {
maybeLoad();
return this.oclStdLibCollection.includesAll(c);
}
@Override
public Boolean excludesAll(UmlgCollection c) {
maybeLoad();
return this.oclStdLibCollection.excludesAll(c);
}
@Override
public Boolean notEmpty() {
maybeLoad();
return this.oclStdLibCollection.notEmpty();
}
@Override
public E max() {
maybeLoad();
return this.oclStdLibCollection.max();
}
@Override
public E min() {
maybeLoad();
return this.oclStdLibCollection.min();
}
@Override
public E sum() {
maybeLoad();
return this.oclStdLibCollection.sum();
}
@Override
public UmlgSet> product(UmlgCollection c) {
maybeLoad();
return this.oclStdLibCollection.product(c);
}
@Override
public UmlgCollection flatten() {
maybeLoad();
return this.oclStdLibCollection.flatten();
}
@Override
public UmlgCollection select(BooleanExpressionEvaluator e) {
maybeLoad();
return this.oclStdLibCollection.select(e);
}
@Override
public UmlgCollection collect(BodyExpressionEvaluator e) {
maybeLoad();
return this.oclStdLibCollection.collect(e);
}
@Override
public UmlgCollection collectNested(BodyExpressionEvaluator e) {
maybeLoad();
return this.oclStdLibCollection.collectNested(e);
}
@Override
public Boolean isUnique(BodyExpressionEvaluator e) {
maybeLoad();
return this.oclStdLibCollection.isUnique(e);
}
@Override
public Boolean exists(BooleanExpressionEvaluator v) {
maybeLoad();
return this.oclStdLibCollection.exists(v);
}
@Override
public Boolean forAll(BooleanExpressionEvaluator v) {
maybeLoad();
return this.oclStdLibCollection.forAll(v);
}
protected boolean validateElementType(E e) {
if (this.umlgRuntimeProperty.isManyPrimitive() || this.umlgRuntimeProperty.isOnePrimitive()) {
if (!(e instanceof String) && !(e instanceof Boolean) && !(e instanceof Integer) &&
!(e instanceof Long) && !(e instanceof Float) && !(e instanceof Double) &&
!(e instanceof Byte) && !(e instanceof Short)) {
throw new IllegalStateException(String.format("Expected primitive got %s", e.getClass().getName()));
}
} else if (this.umlgRuntimeProperty.isManyEnumeration() || this.umlgRuntimeProperty.isOneEnumeration()) {
if (!(e instanceof UmlgEnum)) {
throw new IllegalStateException(String.format("Expected %s got %s", UmlgEnum.class.getName(), e.getClass().getName()));
}
} else if (this.umlgRuntimeProperty.getDataTypeEnum() != null) {
if (!(e.getClass().equals(this.umlgRuntimeProperty.getDataTypeEnum().getType()))) {
throw new IllegalStateException(String.format("Expected %s got %s", this.umlgRuntimeProperty.getDataTypeEnum().getType().getName(), e.getClass().getName()));
}
}
return true;
}
private void setDataTypeOnVertex(Vertex v, E e) {
if (e instanceof UmlgType) {
((UmlgType) e).setOnVertex(v, getPersistentName());
} else {
v.property(getPersistentName(), UmlgFormatter.format(getDataTypeEnum(), e));
}
}
private void loadOneDataType() {
this.vertex.property(getPersistentName()).ifPresent(
s -> {
E result;
DataTypeEnum dte = getDataTypeEnum();
switch (dte) {
case Password:
Password password = new Password();
password.loadFromVertex(this.vertex, getPersistentName());
result = (E) password;
break;
default:
result = UmlgFormatter.parse(getDataTypeEnum(), s);
}
this.internalCollection.add(result);
}
);
this.loaded = true;
}
private void loadManyDataType() {
Property manyProperty = this.vertex.property(getPersistentName());
if (manyProperty.isPresent()) {
this.internalCollection.clear();
Collection coll = UmlgFormatter.convertFromArray(this.umlgRuntimeProperty.getDataTypeEnum(), manyProperty.value());
this.internalCollection.addAll(coll);
}
}
protected void loadUmlgNodes() {
for (Iterator iter = getVertices(); iter.hasNext(); ) {
Vertex vertex = iter.next();
E node;
try {
Class> c = getClassToInstantiate(vertex);
if (c.isEnum()) {
throw new RuntimeException();
} else if (UmlgMetaNode.class.isAssignableFrom(c)) {
Method m = c.getDeclaredMethod("getInstance", new Class[0]);
node = (E) m.invoke(null);
} else if (UmlgNode.class.isAssignableFrom(c)) {
node = (E) c.getConstructor(Vertex.class).newInstance(vertex);
} else {
throw new RuntimeException();
}
this.internalCollection.add(node);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
protected void loadManyEnumeration() {
Property manyProperty = this.vertex.property(getPersistentName());
if (manyProperty.isPresent()) {
this.internalCollection.clear();
String[] value = vertex.value(getPersistentName());
for (String enumerationAsString : value) {
E node = (E) Enum.valueOf((Class extends Enum>) this.umlgRuntimeProperty.getPropertyType(), enumerationAsString);
this.internalCollection.add(node);
}
}
}
protected void loadManyPrimitive() {
Property manyProperty = this.vertex.property(getPersistentName());
if (manyProperty.isPresent()) {
this.internalCollection.clear();
Class propertyType = this.umlgRuntimeProperty.getPropertyType();
List list;
if (propertyType.isAssignableFrom(String.class)) {
list = Arrays.asList((E[]) (manyProperty.value()));
} else if (propertyType.isAssignableFrom(Integer.class)) {
list = Arrays.asList((E[]) ArrayUtils.toObject((int[]) manyProperty.value()));
} else if (propertyType.isAssignableFrom(Long.class)) {
list = Arrays.asList((E[]) ArrayUtils.toObject((long[]) manyProperty.value()));
} else if (propertyType.isAssignableFrom(Double.class)) {
list = Arrays.asList((E[]) ArrayUtils.toObject((double[]) manyProperty.value()));
} else if (propertyType.isAssignableFrom(Float.class)) {
list = Arrays.asList((E[]) ArrayUtils.toObject((float[]) manyProperty.value()));
} else if (propertyType.isAssignableFrom(Boolean.class)) {
list = Arrays.asList((E[]) ArrayUtils.toObject((boolean[]) manyProperty.value()));
} else if (propertyType.isAssignableFrom(Byte.class)) {
list = Arrays.asList((E[]) ArrayUtils.toObject((byte[]) manyProperty.value()));
} else {
throw new IllegalStateException("Unknown propertyType " + propertyType.toString());
}
this.internalCollection.addAll(list);
}
}
protected Collection convertToArrayCollection() {
return new ArrayList<>(this.internalCollection.size() + 1);
}
protected Object convertToArray(E e) {
//the element has already been added to the internalCollection
if (this.umlgRuntimeProperty.getDataTypeEnum() != null) {
if (e instanceof UmlgType) {
throw new RuntimeException();
} else {
return UmlgFormatter.convertToArray(getDataTypeEnum(), this.internalCollection);
}
} else if (isManyEnumeration()) {
Collection enumerationAsList = convertToArrayCollection();
for (E enumeration : this.internalCollection) {
enumerationAsList.add(((Enum>) enumeration).name());
}
return enumerationAsList.toArray(new String[enumerationAsList.size()]);
} else {
Class propertyType = this.umlgRuntimeProperty.getPropertyType();
if (propertyType.isAssignableFrom(String.class)) {
return this.internalCollection.toArray(new String[this.internalCollection.size()]);
} else if (propertyType.isAssignableFrom(Integer.class)) {
return ArrayUtils.toPrimitive(this.internalCollection.toArray(new Integer[this.internalCollection.size()]));
} else if (propertyType.isAssignableFrom(Long.class)) {
return ArrayUtils.toPrimitive(this.internalCollection.toArray(new Long[this.internalCollection.size()]));
} else if (propertyType.isAssignableFrom(Double.class)) {
return ArrayUtils.toPrimitive(this.internalCollection.toArray(new Double[this.internalCollection.size()]));
} else if (propertyType.isAssignableFrom(Float.class)) {
return ArrayUtils.toPrimitive(this.internalCollection.toArray(new Float[this.internalCollection.size()]));
} else if (propertyType.isAssignableFrom(Boolean.class)) {
return ArrayUtils.toPrimitive(this.internalCollection.toArray(new Boolean[this.internalCollection.size()]));
} else if (propertyType.isAssignableFrom(Byte.class)) {
return ArrayUtils.toPrimitive(this.internalCollection.toArray(new Byte[this.internalCollection.size()]));
} else {
throw new IllegalStateException("Unknown propertyType " + propertyType.toString());
}
}
}
protected Object convertToArrayForRemoval() {
if (this.umlgRuntimeProperty.getDataTypeEnum() != null) {
return UmlgFormatter.convertToArray(getDataTypeEnum(), this.internalCollection);
} else if (isManyEnumeration()) {
Collection enumerationAsList = convertToArrayCollection();
for (E enumeration : this.internalCollection) {
enumerationAsList.add(((Enum>) enumeration).name());
}
return enumerationAsList.toArray(new String[enumerationAsList.size()]);
} else {
Class propertyType = this.umlgRuntimeProperty.getPropertyType();
if (propertyType.isAssignableFrom(String.class)) {
return this.internalCollection.toArray(new String[this.internalCollection.size()]);
} else if (propertyType.isAssignableFrom(Integer.class)) {
return ArrayUtils.toPrimitive(this.internalCollection.toArray(new Integer[this.internalCollection.size()]));
} else if (propertyType.isAssignableFrom(Long.class)) {
return ArrayUtils.toPrimitive(this.internalCollection.toArray(new Long[this.internalCollection.size()]));
} else if (propertyType.isAssignableFrom(Double.class)) {
return ArrayUtils.toPrimitive(this.internalCollection.toArray(new Double[this.internalCollection.size()]));
} else if (propertyType.isAssignableFrom(Float.class)) {
return ArrayUtils.toPrimitive(this.internalCollection.toArray(new Float[this.internalCollection.size()]));
} else if (propertyType.isAssignableFrom(Boolean.class)) {
return ArrayUtils.toPrimitive(this.internalCollection.toArray(new Boolean[this.internalCollection.size()]));
} else {
throw new IllegalStateException("Unknown propertyType " + propertyType.toString());
}
}
}
protected boolean isEmbedded() {
return isOnePrimitive() || isManyPrimitive() || isOneEnumeration() || isManyEnumeration() ||
(getDataTypeEnum() != null && (isOneToMany() || isManyToMany()));
}
}