use of org.structr.api.DatabaseService in project structr by structr.
the class MaintenanceTest method testBulkCreateLabelsCommand.
@Test
public void testBulkCreateLabelsCommand() {
try {
final DatabaseService graphDb = app.getDatabaseService();
final Set<Label> expectedLabels = new LinkedHashSet<>();
expectedLabels.add(graphDb.forName(Label.class, "Principal"));
expectedLabels.add(graphDb.forName(Label.class, "Group"));
expectedLabels.add(graphDb.forName(Label.class, "AccessControllable"));
expectedLabels.add(graphDb.forName(Label.class, "AbstractNode"));
expectedLabels.add(graphDb.forName(Label.class, "NodeInterface"));
expectedLabels.add(graphDb.forName(Label.class, "CMISInfo"));
expectedLabels.add(graphDb.forName(Label.class, "CMISItemInfo"));
if (graphDb.getTenantIdentifier() != null) {
expectedLabels.add(graphDb.forName(Label.class, graphDb.getTenantIdentifier()));
}
// intentionally create raw Neo4j transaction and create nodes in there
try (Transaction tx = graphDb.beginTx()) {
for (int i = 0; i < 100; i++) {
final Node test = graphDb.createNode(Collections.EMPTY_SET, Collections.EMPTY_MAP);
// set ID and type so that the rebuild index command identifies it as a Structr node.
test.setProperty("type", "Group");
test.setProperty("id", UUID.randomUUID().toString().replace("-", ""));
}
// this is important.... :)
tx.success();
}
/*
* This test will fail with the new Neo4j 3.0 Bolt interface, because
* there is no separation between a (Lucene-based) index and the
* database values any more. Nodes are selected by their 'type'
* property and will always be found even if NOT created using Structr
* methods.
// nodes should not be found yet..
try (final Tx tx = app.tx()) {
// check nodes, we should find no Groups here
assertEquals(0, app.nodeQuery(Group.class).getResult().size());
}
*/
// test rebuild index and create labels
// app.command(BulkRebuildIndexCommand.class).execute(new LinkedHashMap<>());
app.command(BulkCreateLabelsCommand.class).execute(new LinkedHashMap<>());
// nodes should now be visible to Structr
try (final Tx tx = app.tx()) {
// check nodes, we should find 100 Groups here
assertEquals(100, app.nodeQuery(Group.class).getResult().size());
// check nodes
for (final Group group : app.nodeQuery(Group.class)) {
final Set<Label> labels = Iterables.toSet(group.getNode().getLabels());
assertEquals("Invalid number of labels", expectedLabels.size(), labels.size());
assertTrue("Invalid labels found", labels.containsAll(expectedLabels));
}
tx.success();
}
} catch (FrameworkException fex) {
logger.warn("", fex);
fail("Unexpected exception.");
}
}
use of org.structr.api.DatabaseService in project structr by structr.
the class PropertyTest method testModifyType.
// ----- type property tests -----
@Test
public void testModifyType() {
final DatabaseService db = StructrApp.getInstance().getDatabaseService();
final Set<Label> labelsBefore = new LinkedHashSet<>();
final Set<Label> labelsAfter = new LinkedHashSet<>();
String id = null;
labelsBefore.add(db.forName(Label.class, AccessControllable.class.getSimpleName()));
labelsBefore.add(db.forName(Label.class, TestFour.class.getSimpleName()));
labelsAfter.add(db.forName(Label.class, AccessControllable.class.getSimpleName()));
labelsAfter.add(db.forName(Label.class, TestFive.class.getSimpleName()));
try (final Tx tx = app.tx()) {
// create entity of type TestFour
final TestFour testEntity = createTestNode(TestFour.class);
// check if node exists
assertNotNull(testEntity);
// check labels before type change
assertTrue(Iterables.toSet(testEntity.getNode().getLabels()).containsAll(labelsBefore));
// save ID for later use
id = testEntity.getUuid();
// change type to TestFive
// system properties have to be unlocked now, admin rights are not enough anymore
testEntity.unlockSystemPropertiesOnce();
testEntity.setProperty(GraphObject.type, TestFive.class.getSimpleName());
// commit transaction
tx.success();
} catch (FrameworkException fex) {
logger.warn("", fex);
fail("Unexpected exception");
}
try (final Tx tx = app.tx()) {
final TestFive testEntity = app.get(TestFive.class, id);
assertNotNull(testEntity);
// check labels after type change
assertTrue(Iterables.toSet(testEntity.getNode().getLabels()).containsAll(labelsAfter));
} catch (FrameworkException fex) {
logger.warn("", fex);
fail("Unexpected exception");
}
}
use of org.structr.api.DatabaseService in project structr by structr.
the class SchemaImporter method analyzeSchema.
public void analyzeSchema() {
final App app = StructrApp.getInstance();
final FileBasedHashLongMap<NodeInfo> nodeIdMap = new FileBasedHashLongMap<>(userHome + File.separator + ".structrSchemaAnalyzer");
final DatabaseService graphDb = app.getDatabaseService();
final ConfigurationProvider configuration = Services.getInstance().getConfigurationProvider();
final Set<NodeInfo> nodeTypes = new LinkedHashSet<>();
final Set<RelationshipInfo> relationships = new LinkedHashSet<>();
final Map<String, SchemaNode> schemaNodes = new LinkedHashMap<>();
final Map<String, List<TypeInfo>> typeInfoTypeMap = new LinkedHashMap<>();
final List<TypeInfo> reducedTypeInfos = new LinkedList<>();
final List<TypeInfo> typeInfos = new LinkedList<>();
Iterator<Relationship> relIterator = null;
Iterator<Node> nodeIterator = null;
info("Fetching all nodes iterator..");
try (final Tx tx = app.tx()) {
nodeIterator = Iterables.filter(new StructrAndSpatialPredicate(false, false, true), graphDb.getAllNodes()).iterator();
tx.success();
} catch (FrameworkException fex) {
logger.warn("", fex);
}
info("Starting to analyze nodes..");
bulkGraphOperation(SecurityContext.getSuperUserInstance(), nodeIterator, 100000, "Analyzing nodes", new BulkGraphOperation<Node>() {
@Override
public void handleGraphObject(final SecurityContext securityContext, final Node node) throws FrameworkException {
final NodeInfo nodeInfo = new NodeInfo(node);
// hashcode of nodeInfo is derived from its property and type signature!
nodeTypes.add(nodeInfo);
// add node ID to our new test datastructure
nodeIdMap.add(nodeInfo, node.getId());
}
});
info("Identifying common base classes..");
try (final Tx tx = app.tx(true, false, false)) {
// nodeTypes now contains all existing node types and their property sets
identifyCommonBaseClasses(app, nodeTypes, nodeIdMap, typeInfos);
tx.success();
} catch (FrameworkException fex) {
logger.warn("", fex);
}
info("Collecting type information..");
try (final Tx tx = app.tx(true, false, false)) {
// group type infos by type
collectTypeInfos(typeInfos, typeInfoTypeMap);
tx.success();
} catch (FrameworkException fex) {
logger.warn("", fex);
}
info("Aggregating type information..");
try (final Tx tx = app.tx(true, false, false)) {
// reduce type infos with more than one type
reduceTypeInfos(typeInfoTypeMap, reducedTypeInfos);
tx.success();
} catch (FrameworkException fex) {
logger.warn("", fex);
}
info("Identifying property sets..");
try (final Tx tx = app.tx(true, false, false)) {
// intersect property sets of type infos
intersectPropertySets(reducedTypeInfos);
tx.success();
} catch (FrameworkException fex) {
logger.warn("", fex);
}
info("Sorting result..");
try (final Tx tx = app.tx(true, false, false)) {
// sort type infos
Collections.sort(reducedTypeInfos, new HierarchyComparator(false));
tx.success();
} catch (FrameworkException fex) {
logger.warn("", fex);
}
final Map<String, TypeInfo> reducedTypeInfoMap = new LinkedHashMap<>();
for (final TypeInfo info : reducedTypeInfos) {
final String type = info.getPrimaryType();
// map TypeInfo to type for later use
reducedTypeInfoMap.put(type, info);
info("Starting with setting of type and ID for type {}", type);
bulkGraphOperation(SecurityContext.getSuperUserInstance(), info.getNodeIds().iterator(), 10000, "Setting type and ID", new BulkGraphOperation<Long>() {
@Override
public void handleGraphObject(SecurityContext securityContext, Long nodeId) throws FrameworkException {
final Node node = graphDb.getNodeById(nodeId);
node.setProperty(GraphObject.id.dbName(), NodeServiceCommand.getNextUuid());
node.setProperty(GraphObject.type.dbName(), type);
}
});
}
info("Fetching all relationships iterator..");
try (final Tx tx = app.tx(true, false, false)) {
relIterator = Iterables.filter(new StructrAndSpatialPredicate(false, false, true), graphDb.getAllRelationships()).iterator();
tx.success();
} catch (FrameworkException fex) {
logger.warn("", fex);
}
info("Starting with analyzing relationships..");
bulkGraphOperation(SecurityContext.getSuperUserInstance(), relIterator, 10000, "Analyzing relationships", new BulkGraphOperation<Relationship>() {
@Override
public void handleGraphObject(SecurityContext securityContext, Relationship rel) throws FrameworkException {
final Node startNode = rel.getStartNode();
final Node endNode = rel.getEndNode();
// make sure node has been successfully identified above
if (startNode.hasProperty("type") && endNode.hasProperty("type")) {
final String relationshipType = rel.getType().name();
final String startNodeType = (String) startNode.getProperty("type");
final String endNodeType = (String) endNode.getProperty("type");
relationships.add(new RelationshipInfo(startNodeType, endNodeType, relationshipType));
// create combined type on imported relationship
if (startNodeType != null && endNodeType != null) {
final String combinedType = getCombinedType(startNodeType, relationshipType, endNodeType);
logger.debug("Combined relationship type {} found for rel type {}, start node type {}, end node type {}", new Object[] { combinedType, relationshipType, startNodeType, endNodeType });
rel.setProperty(GraphObject.type.dbName(), combinedType);
}
// create ID on imported relationship
rel.setProperty(GraphObject.id.dbName(), NodeServiceCommand.getNextUuid());
}
}
});
info("Grouping relationships..");
// group relationships by type
final Map<String, List<RelationshipInfo>> relTypeInfoMap = new LinkedHashMap<>();
for (final RelationshipInfo relInfo : relationships) {
// final String relType = relInfo.getRelType();
final String combinedType = getCombinedType(relInfo.getStartNodeType(), relInfo.getRelType(), relInfo.getEndNodeType());
List<RelationshipInfo> infos = relTypeInfoMap.get(combinedType);
if (infos == null) {
infos = new LinkedList<>();
relTypeInfoMap.put(combinedType, infos);
}
infos.add(relInfo);
}
info("Aggregating relationship information..");
final List<RelationshipInfo> reducedRelationshipInfos = new ArrayList<>();
if (Settings.InheritanceDetection.getValue()) {
// reduce relationship infos into one
for (final List<RelationshipInfo> infos : relTypeInfoMap.values()) {
reducedRelationshipInfos.addAll(reduceNodeTypes(infos, reducedTypeInfoMap));
}
} else {
reducedRelationshipInfos.addAll(relationships);
}
info("Starting with schema node creation..");
bulkGraphOperation(SecurityContext.getSuperUserInstance(), reducedTypeInfos.iterator(), 100000, "Creating schema nodes", new BulkGraphOperation<TypeInfo>() {
@Override
public void handleGraphObject(SecurityContext securityContext, TypeInfo typeInfo) throws FrameworkException {
final String type = typeInfo.getPrimaryType();
if (!"ReferenceNode".equals(type)) {
final Map<String, Class> props = typeInfo.getPropertySet();
final PropertyMap propertyMap = new PropertyMap();
// add properties
for (final Map.Entry<String, Class> propertyEntry : props.entrySet()) {
final String propertyName = propertyEntry.getKey();
final Class propertyType = propertyEntry.getValue();
// handle array types differently
String propertyTypeName = propertyType.getSimpleName();
if (propertyType.isArray()) {
// remove "[]" from the end and append "Array" to match the appropriate parser
propertyTypeName = propertyTypeName.substring(0, propertyTypeName.length() - 2).concat("Array");
}
propertyMap.put(new StringProperty("_".concat(propertyName)), propertyTypeName);
}
// set node type which is in "name" property
propertyMap.put(AbstractNode.name, type);
// check if there is an existing Structr entity with the same type
// and make the dynamic class extend the existing class if yes.
final Class existingType = configuration.getNodeEntityClass(type);
if (existingType != null) {
propertyMap.put(SchemaNode.extendsClass, existingType.getName());
} else if (!typeInfo.getOtherTypes().isEmpty()) {
// only the first supertype is supported
propertyMap.put(SchemaNode.extendsClass, typeInfo.getSuperclass(reducedTypeInfoMap));
}
final SchemaNode existingNode = app.nodeQuery(SchemaNode.class).andName(type).getFirst();
if (existingNode != null) {
for (final Entry<PropertyKey, Object> entry : propertyMap.entrySet()) {
existingNode.setProperty(entry.getKey(), entry.getValue());
}
schemaNodes.put(type, existingNode);
} else {
// create schema node
schemaNodes.put(type, app.create(SchemaNode.class, propertyMap));
}
}
}
});
info("Starting with schema relationship creation..");
bulkGraphOperation(SecurityContext.getSuperUserInstance(), reducedRelationshipInfos.iterator(), 100000, "Creating schema relationships", new BulkGraphOperation<RelationshipInfo>() {
@Override
public void handleGraphObject(SecurityContext securityContext, RelationshipInfo template) throws FrameworkException {
final String startNodeType = template.getStartNodeType();
final String endNodeType = template.getEndNodeType();
if (startNodeType != null && endNodeType != null) {
final SchemaNode startNode = schemaNodes.get(startNodeType);
final SchemaNode endNode = schemaNodes.get(endNodeType);
if (startNode != null && endNode != null) {
final String relationshipType = template.getRelType();
final PropertyMap propertyMap = new PropertyMap();
propertyMap.put(SchemaRelationshipNode.sourceId, startNode.getUuid());
propertyMap.put(SchemaRelationshipNode.targetId, endNode.getUuid());
propertyMap.put(SchemaRelationshipNode.relationshipType, relationshipType);
app.create(SchemaRelationshipNode.class, propertyMap);
} else {
info("Unable to create schema relationship node for {} -> {}, no schema nodes found", startNodeType, endNodeType);
}
}
}
});
info("Starting with index rebuild..");
// rebuild index
app.command(BulkRebuildIndexCommand.class).execute(Collections.EMPTY_MAP);
}
use of org.structr.api.DatabaseService in project structr by structr.
the class BulkDeleteSoftDeletedNodesCommand method execute.
// ~--- methods --------------------------------------------------------
@Override
public void execute(final Map<String, Object> properties) throws FrameworkException {
final DatabaseService graphDb = (DatabaseService) arguments.get("graphDb");
final SecurityContext superUserContext = SecurityContext.getSuperUserInstance();
final NodeFactory nodeFactory = new NodeFactory(superUserContext, true, false);
if (graphDb != null) {
final Iterator<AbstractNode> nodeIterator = Iterables.map(nodeFactory, Iterables.filter(new StructrAndSpatialPredicate(true, false, false), graphDb.getAllNodes())).iterator();
final boolean erase;
if (properties.containsKey("erase") && properties.get("erase").equals("true")) {
erase = true;
} else {
erase = false;
}
bulkGraphOperation(securityContext, nodeIterator, 1000, "DeleteSoftDeletedNodes", new BulkGraphOperation<AbstractNode>() {
@Override
public void handleGraphObject(SecurityContext securityContext, AbstractNode node) {
if (node.isDeleted()) {
logger.info("Found deleted node: {}", node);
if (erase) {
try {
StructrApp.getInstance(securityContext).delete(node);
} catch (FrameworkException ex) {
logger.warn("Could not delete node " + node, ex);
}
}
}
}
@Override
public void handleThrowable(SecurityContext securityContext, Throwable t, AbstractNode node) {
logger.warn("Unable to set properties of node {}: {}", new Object[] { node.getUuid(), t.getMessage() });
}
@Override
public void handleTransactionFailure(SecurityContext securityContext, Throwable t) {
logger.warn("Unable to set node properties: {}", t.getMessage());
}
});
}
logger.info("Done");
}
use of org.structr.api.DatabaseService 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.");
}
Aggregations