use of org.structr.api.graph.Node in project structr by structr.
the class SyncCommand method importDatabase.
private static void importDatabase(final DatabaseService graphDb, final SecurityContext securityContext, final ZipInputStream zis, boolean doValidation, final Long batchSize) throws FrameworkException, IOException {
final App app = StructrApp.getInstance();
final DataInputStream dis = new DataInputStream(new BufferedInputStream(zis));
final long internalBatchSize = batchSize != null ? batchSize : 200;
final String uuidPropertyName = GraphObject.id.dbName();
final Map<String, Node> uuidMap = new LinkedHashMap<>();
final Set<Long> deletedNodes = new HashSet<>();
double t0 = System.nanoTime();
PropertyContainer currentObject = null;
String currentKey = null;
boolean finished = false;
long totalNodeCount = 0;
long totalRelCount = 0;
do {
try (final Tx tx = app.tx(doValidation)) {
final List<Relationship> rels = new LinkedList<>();
final List<Node> nodes = new LinkedList<>();
long nodeCount = 0;
long relCount = 0;
do {
try {
// store current position
dis.mark(4);
// read one byte
byte objectType = dis.readByte();
// skip newlines
if (objectType == '\n') {
continue;
}
if (objectType == 'N') {
// break loop after 200 objects, commit and restart afterwards
if (nodeCount + relCount >= internalBatchSize) {
dis.reset();
break;
}
currentObject = graphDb.createNode(Collections.EMPTY_SET, Collections.EMPTY_MAP);
nodeCount++;
// store for later use
nodes.add((Node) currentObject);
} else if (objectType == 'R') {
// break look after 200 objects, commit and restart afterwards
if (nodeCount + relCount >= internalBatchSize) {
dis.reset();
break;
}
String startId = (String) deserialize(dis);
String endId = (String) deserialize(dis);
String relTypeName = (String) deserialize(dis);
Node endNode = uuidMap.get(endId);
Node startNode = uuidMap.get(startId);
if (startNode != null && endNode != null) {
if (deletedNodes.contains(startNode.getId()) || deletedNodes.contains(endNode.getId())) {
System.out.println("NOT creating relationship between deleted nodes..");
currentObject = null;
currentKey = null;
} else {
RelationshipType relType = RelationshipType.forName(relTypeName);
currentObject = startNode.createRelationshipTo(endNode, relType);
// store for later use
rels.add((Relationship) currentObject);
relCount++;
}
} else {
System.out.println("NOT creating relationship of type " + relTypeName + ", start: " + startId + ", end: " + endId);
currentObject = null;
currentKey = null;
}
} else {
// reset if not at the beginning of a line
dis.reset();
if (currentKey == null) {
try {
currentKey = (String) deserialize(dis);
} catch (Throwable t) {
logger.warn("", t);
}
} else {
final Object obj = deserialize(dis);
if (obj != null && currentObject != null) {
if (uuidPropertyName.equals(currentKey) && currentObject instanceof Node) {
final String uuid = (String) obj;
uuidMap.put(uuid, (Node) currentObject);
}
if (currentKey.length() != 0) {
// store object in DB
currentObject.setProperty(currentKey, obj);
// set type label
if (currentObject instanceof Node && NodeInterface.type.dbName().equals(currentKey)) {
((Node) currentObject).addLabel(graphDb.forName(Label.class, (String) obj));
}
} else {
logger.error("Invalid property key for value {}, ignoring", obj);
}
} else {
logger.warn("No current object to store property in.");
}
currentKey = null;
}
}
} catch (EOFException eofex) {
finished = true;
}
} while (!finished);
totalNodeCount += nodeCount;
totalRelCount += relCount;
logger.info("Imported {} nodes and {} rels, committing transaction..", new Object[] { totalNodeCount, totalRelCount });
tx.success();
}
} while (!finished);
// build schema
try (final Tx tx = app.tx()) {
SchemaHelper.reloadSchema(new ErrorBuffer(), securityContext.getSessionId());
tx.success();
} catch (FrameworkException fex) {
logger.warn("", fex);
}
final Map<String, Object> params = new HashMap<>();
params.put("removeUnused", false);
// set correct labels after schema has been compiled
app.command(BulkCreateLabelsCommand.class).execute(params);
double t1 = System.nanoTime();
double time = ((t1 - t0) / 1000000000.0);
DecimalFormat decimalFormat = new DecimalFormat("0.000000000", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
logger.info("Import done in {} s", decimalFormat.format(time));
}
use of org.structr.api.graph.Node in project structr by structr.
the class SyncCommand method groupByTypeAndName.
private static Map<String, List<Node>> groupByTypeAndName(final Iterable<Node> nodes) {
final Map<String, List<Node>> groupedNodes = new LinkedHashMap<>();
for (final Node node : nodes) {
if (node.hasProperty("name") && node.hasProperty("type")) {
final String typeAndName = node.getProperty("type") + "." + node.getProperty("name");
List<Node> nodeList = groupedNodes.get(typeAndName);
if (nodeList == null) {
nodeList = new LinkedList<>();
groupedNodes.put(typeAndName, nodeList);
}
nodeList.add(node);
}
}
return groupedNodes;
}
use of org.structr.api.graph.Node in project structr by structr.
the class BulkFixNodePropertiesCommand method execute.
@Override
public void execute(Map<String, Object> attributes) throws FrameworkException {
final String propertyName = (String) attributes.get("name");
final String entityTypeName = (String) attributes.get("type");
if (entityTypeName != null) {
final Class type = SchemaHelper.getEntityClassForRawType(entityTypeName);
if (type != null) {
final DatabaseService db = StructrApp.getInstance(securityContext).getDatabaseService();
final NodeFactory factory = new NodeFactory(securityContext);
final Iterator<AbstractNode> nodeIterator = Iterables.map(factory, db.getNodesByLabel(entityTypeName)).iterator();
logger.info("Trying to fix properties of all {} nodes", type.getSimpleName());
long nodeCount = bulkGraphOperation(securityContext, nodeIterator, 100, "FixNodeProperties", new BulkGraphOperation<AbstractNode>() {
private void fixProperty(AbstractNode node, Property propertyToFix) {
Node databaseNode = node.getNode();
if (databaseNode.hasProperty(propertyToFix.dbName())) {
// check value with property converter
PropertyConverter converter = propertyToFix.databaseConverter(securityContext, node);
if (converter != null) {
try {
Object value = databaseNode.getProperty(propertyToFix.dbName());
converter.revert(value);
} catch (ClassCastException cce) {
// exception, needs fix
String databaseName = propertyToFix.dbName();
Object databaseValue = databaseNode.getProperty(databaseName);
Object correctedValue = propertyToFix.fixDatabaseProperty(databaseValue);
if (databaseValue != null && correctedValue != null) {
try {
// try to set database value to corrected value
databaseNode.setProperty(databaseName, correctedValue);
} catch (Throwable t) {
logger.warn("Unable to fix property {} of {} with UUID {} which is of type {}", new Object[] { propertyToFix.dbName(), type.getSimpleName(), node.getUuid(), databaseValue != null ? databaseValue.getClass() : "null" });
}
}
} catch (Throwable t) {
// log exceptions of other types
logger.warn("", t);
}
}
}
}
@Override
public void handleGraphObject(SecurityContext securityContext, AbstractNode node) {
if (propertyName != null) {
PropertyKey key = StructrApp.getConfiguration().getPropertyKeyForDatabaseName(type, propertyName);
if (key != null) {
// needs type cast to Property to use fixDatabaseProperty method
if (key instanceof Property) {
fixProperty(node, (Property) key);
}
}
} else {
for (PropertyKey key : node.getPropertyKeys(PropertyView.All)) {
// needs type cast to Property to use fixDatabaseProperty method
if (key instanceof Property) {
fixProperty(node, (Property) key);
}
}
}
}
});
logger.info("Fixed {} nodes", nodeCount);
return;
}
}
logger.info("Unable to determine property and/or entity type to fix.");
}
use of org.structr.api.graph.Node in project structr by structr.
the class CreateNodeCommand method createNode.
// ----- private methods -----
private Node createNode(final DatabaseService graphDb, final Principal user, final Set<String> labels, final Map<String, Object> properties) throws FrameworkException {
final Map<String, Object> parameters = new HashMap<>();
final Map<String, Object> ownsProperties = new HashMap<>();
final Map<String, Object> securityProperties = new HashMap<>();
final StringBuilder buf = new StringBuilder();
final String newUuid = (String) properties.get("id");
final String tenantId = graphDb.getTenantIdentifier();
if (user != null && user.shouldSkipSecurityRelationships() == false) {
buf.append("MATCH (u:Principal) WHERE id(u) = {userId}");
buf.append(" CREATE (u)-[o:OWNS {ownsProperties}]->(n");
if (tenantId != null) {
buf.append(":");
buf.append(tenantId);
}
for (final String label : labels) {
buf.append(":");
buf.append(label);
}
buf.append(" {nodeProperties})<-[s:SECURITY {securityProperties}]-(u)");
buf.append(" RETURN n");
// configure OWNS relationship
ownsProperties.put(GraphObject.id.dbName(), getNextUuid());
ownsProperties.put(GraphObject.type.dbName(), PrincipalOwnsNode.class.getSimpleName());
ownsProperties.put(AbstractRelationship.sourceId.dbName(), user.getUuid());
ownsProperties.put(AbstractRelationship.targetId.dbName(), newUuid);
// configure SECURITY relationship
securityProperties.put(Security.allowed.dbName(), new String[] { Permission.read.name(), Permission.write.name(), Permission.delete.name(), Permission.accessControl.name() });
securityProperties.put(GraphObject.id.dbName(), getNextUuid());
securityProperties.put(GraphObject.type.dbName(), Security.class.getSimpleName());
securityProperties.put(AbstractRelationship.sourceId.dbName(), user.getUuid());
securityProperties.put(AbstractRelationship.targetId.dbName(), newUuid);
// store properties in statement
parameters.put("userId", user.getId());
parameters.put("ownsProperties", ownsProperties);
parameters.put("securityProperties", securityProperties);
} else {
buf.append("CREATE (n");
if (tenantId != null) {
buf.append(":");
buf.append(tenantId);
}
for (final String label : labels) {
buf.append(":");
buf.append(label);
}
buf.append(" {nodeProperties})");
buf.append(" RETURN n");
}
// make properties available to Cypher statement
parameters.put("nodeProperties", properties);
final NativeResult result = graphDb.execute(buf.toString(), parameters);
try {
if (result.hasNext()) {
final Map<String, Object> data = result.next();
final Node newNode = (Node) data.get("n");
return newNode;
}
} catch (DataFormatException dex) {
throw new FrameworkException(422, dex.getMessage());
} catch (ConstraintViolationException qex) {
throw new FrameworkException(422, qex.getMessage());
}
throw new RuntimeException("Unable to create new node.");
}
use of org.structr.api.graph.Node in project structr by structr.
the class CreateRelationshipCommand method createRelationship.
private synchronized <A extends NodeInterface, B extends NodeInterface, R extends Relation<A, B, ?, ?>> R createRelationship(final A fromNode, final B toNode, final Class<R> relType, final PropertyMap attributes) throws FrameworkException {
// disable updating access time when creating relationships
securityContext.disableModificationOfAccessTime();
final RelationshipFactory<R> factory = new RelationshipFactory(securityContext);
final PropertyMap properties = new PropertyMap(attributes);
final CreationContainer tmp = new CreationContainer();
final R template = instantiate(relType);
final Node startNode = fromNode.getNode();
final Node endNode = toNode.getNode();
final Date now = new Date();
final Principal user = securityContext.getCachedUser();
template.ensureCardinality(securityContext, fromNode, toNode);
// date properties need converter
AbstractRelationship.createdDate.setProperty(securityContext, tmp, now);
AbstractRelationship.lastModifiedDate.setProperty(securityContext, tmp, now);
// set initial properties manually (caution, this can only be used for primitive properties!)
tmp.getData().put(GraphObject.id.jsonName(), getNextUuid());
tmp.getData().put(GraphObject.type.jsonName(), relType.getSimpleName());
tmp.getData().put(AbstractRelationship.relType.jsonName(), template.name());
tmp.getData().put(AbstractRelationship.sourceId.jsonName(), fromNode.getUuid());
tmp.getData().put(AbstractRelationship.targetId.jsonName(), toNode.getUuid());
tmp.getData().put(AbstractRelationship.visibleToPublicUsers.jsonName(), false);
tmp.getData().put(AbstractRelationship.visibleToAuthenticatedUsers.jsonName(), false);
tmp.getData().put(AbstractRelationship.cascadeDelete.jsonName(), template.getCascadingDeleteFlag());
if (user != null) {
tmp.getData().put(AbstractRelationship.createdBy.jsonName(), user.getUuid());
}
// create relationship including initial properties
final Relationship rel = startNode.createRelationshipTo(endNode, template, tmp.getData());
final R newRel = factory.instantiateWithType(rel, relType, null, true);
if (newRel != null) {
newRel.setProperties(securityContext, properties);
// notify transaction handler
TransactionCommand.relationshipCreated(user, newRel);
// notify relationship of its creation
newRel.onRelationshipCreation();
// iterate post creation transformations
for (Transformation<GraphObject> transformation : StructrApp.getConfiguration().getEntityCreationTransformations(newRel.getClass())) {
transformation.apply(securityContext, newRel);
}
}
// enable access time update again for subsequent calls
securityContext.enableModificationOfAccessTime();
return newRel;
}
Aggregations