Search in sources :

Example 1 with NodeExtender

use of org.structr.schema.compiler.NodeExtender in project structr by structr.

the class SchemaService method reloadSchema.

public static boolean reloadSchema(final ErrorBuffer errorBuffer, final String initiatedBySessionId) {
    final ConfigurationProvider config = StructrApp.getConfiguration();
    final App app = StructrApp.getInstance();
    boolean success = true;
    // compiling must only be done once
    if (compiling.compareAndSet(false, true)) {
        try {
            final Map<String, Map<String, PropertyKey>> removedClasses = new HashMap<>(config.getTypeAndPropertyMapping());
            final Map<String, GraphQLType> graphQLTypes = new LinkedHashMap<>();
            final NodeExtender nodeExtender = new NodeExtender(initiatedBySessionId);
            final Set<String> dynamicViews = new LinkedHashSet<>();
            try (final Tx tx = app.tx()) {
                // collect auto-generated schema nodes
                SchemaService.ensureBuiltinTypesExist();
                // add schema nodes from database
                for (final SchemaNode schemaInfo : app.nodeQuery(SchemaNode.class).getAsList()) {
                    schemaInfo.handleMigration();
                    final String sourceCode = SchemaHelper.getSource(schemaInfo, errorBuffer);
                    if (sourceCode != null) {
                        final String className = schemaInfo.getClassName();
                        // only load dynamic node if there were no errors while generating
                        // the source code (missing modules etc.)
                        nodeExtender.addClass(className, sourceCode);
                        dynamicViews.addAll(schemaInfo.getDynamicViews());
                        // initialize GraphQL engine as well
                        schemaInfo.initializeGraphQL(graphQLTypes);
                    }
                }
                // collect relationship classes
                for (final SchemaRelationshipNode schemaRelationship : app.nodeQuery(SchemaRelationshipNode.class).getAsList()) {
                    nodeExtender.addClass(schemaRelationship.getClassName(), schemaRelationship.getSource(errorBuffer));
                    dynamicViews.addAll(schemaRelationship.getDynamicViews());
                    // initialize GraphQL engine as well
                    schemaRelationship.initializeGraphQL(graphQLTypes);
                }
                // this is a very critical section :)
                synchronized (SchemaService.class) {
                    // clear propagating relationship cache
                    SchemaRelationshipNode.clearPropagatingRelationshipTypes();
                    // compile all classes at once and register
                    final Map<String, Class> newTypes = nodeExtender.compile(errorBuffer);
                    for (final Class newType : newTypes.values()) {
                        // instantiate classes to execute static initializer of helpers
                        try {
                            // do full reload
                            config.registerEntityType(newType);
                            newType.newInstance();
                        } catch (Throwable ignore) {
                        }
                    }
                    // calculate difference between previous and new classes
                    removedClasses.keySet().removeAll(StructrApp.getConfiguration().getTypeAndPropertyMapping().keySet());
                }
                // create properties and views etc.
                for (final SchemaNode schemaNode : app.nodeQuery(SchemaNode.class).getAsList()) {
                    schemaNode.createBuiltInSchemaEntities(errorBuffer);
                }
                success = !errorBuffer.hasError();
                if (success) {
                    // prevent inheritance map from leaking
                    SearchCommand.clearInheritanceMap();
                    AccessPathCache.invalidate();
                    // clear relationship instance cache
                    AbstractNode.clearRelationshipTemplateInstanceCache();
                    // clear permission cache
                    AbstractNode.clearPermissionResolutionCache();
                    // inject views in configuration provider
                    config.registerDynamicViews(dynamicViews);
                    if (Services.calculateHierarchy() || !Services.isTesting()) {
                        calculateHierarchy();
                    }
                    if (Services.updateIndexConfiguration() || !Services.isTesting()) {
                        updateIndexConfiguration(removedClasses);
                    }
                    tx.success();
                    final GraphQLObjectType.Builder queryTypeBuilder = GraphQLObjectType.newObject();
                    // register types in "Query" type
                    for (final Entry<String, GraphQLType> entry : graphQLTypes.entrySet()) {
                        final String className = entry.getKey();
                        final GraphQLType type = entry.getValue();
                        // register type in query type
                        queryTypeBuilder.field(GraphQLFieldDefinition.newFieldDefinition().name(className).type(new GraphQLList(type)).argument(GraphQLArgument.newArgument().name("id").type(Scalars.GraphQLString).build()).argument(GraphQLArgument.newArgument().name("type").type(Scalars.GraphQLString).build()).argument(GraphQLArgument.newArgument().name("name").type(Scalars.GraphQLString).build()).argument(GraphQLArgument.newArgument().name("_page").type(Scalars.GraphQLInt).build()).argument(GraphQLArgument.newArgument().name("_pageSize").type(Scalars.GraphQLInt).build()).argument(GraphQLArgument.newArgument().name("_sort").type(Scalars.GraphQLString).build()).argument(GraphQLArgument.newArgument().name("_desc").type(Scalars.GraphQLBoolean).build()));
                    }
                    // exchange graphQL schema after successful build
                    synchronized (SchemaService.class) {
                        graphQLSchema = GraphQLSchema.newSchema().query(queryTypeBuilder.name("Query").build()).build(new LinkedHashSet<>(graphQLTypes.values()));
                    }
                }
            } catch (FrameworkException fex) {
                logger.error("Unable to compile dynamic schema: {}", fex.getMessage());
                success = false;
                errorBuffer.getErrorTokens().addAll(fex.getErrorBuffer().getErrorTokens());
            } catch (Throwable t) {
                t.printStackTrace();
                logger.error("Unable to compile dynamic schema: {}", t.getMessage());
                success = false;
            }
            if (!success) {
                if (Settings.SchemAutoMigration.getValue()) {
                    // handle migration in separate transaction
                    try (final Tx tx = app.tx()) {
                        // try to handle certain errors automatically
                        handleAutomaticMigration(errorBuffer);
                        tx.success();
                    } catch (FrameworkException fex) {
                    }
                } else {
                    logger.error("Unable to compile dynamic schema, and automatic migration is not enabled. Please set application.schema.automigration = true in structr.conf to enable modification of existing schema classes.");
                }
            }
        } finally {
            // compiling done
            compiling.set(false);
        }
    }
    return success;
}
Also used : StructrApp(org.structr.core.app.StructrApp) App(org.structr.core.app.App) LinkedHashSet(java.util.LinkedHashSet) NodeExtender(org.structr.schema.compiler.NodeExtender) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) GraphQLType(graphql.schema.GraphQLType) LinkedHashMap(java.util.LinkedHashMap) SchemaRelationshipNode(org.structr.core.entity.SchemaRelationshipNode) GraphQLList(graphql.schema.GraphQLList) Tx(org.structr.core.graph.Tx) FrameworkException(org.structr.common.error.FrameworkException) SchemaNode(org.structr.core.entity.SchemaNode) GraphQLObjectType(graphql.schema.GraphQLObjectType) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Aggregations

GraphQLList (graphql.schema.GraphQLList)1 GraphQLObjectType (graphql.schema.GraphQLObjectType)1 GraphQLType (graphql.schema.GraphQLType)1 HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 LinkedHashSet (java.util.LinkedHashSet)1 Map (java.util.Map)1 FrameworkException (org.structr.common.error.FrameworkException)1 App (org.structr.core.app.App)1 StructrApp (org.structr.core.app.StructrApp)1 SchemaNode (org.structr.core.entity.SchemaNode)1 SchemaRelationshipNode (org.structr.core.entity.SchemaRelationshipNode)1 Tx (org.structr.core.graph.Tx)1 NodeExtender (org.structr.schema.compiler.NodeExtender)1