Search in sources :

Example 76 with App

use of org.structr.core.app.App in project structr by structr.

the class SchemaHelper method getSource.

public static String getSource(final AbstractSchemaNode schemaNode, final ErrorBuffer errorBuffer) throws FrameworkException {
    final Collection<StructrModule> modules = StructrApp.getConfiguration().getModules().values();
    final App app = StructrApp.getInstance();
    final Map<String, List<ActionEntry>> methods = new LinkedHashMap<>();
    final Map<String, Set<String>> viewProperties = new LinkedHashMap<>();
    final List<String> propertyValidators = new LinkedList<>();
    final Set<String> existingPropertyNames = new LinkedHashSet<>();
    final Set<String> compoundIndexKeys = new LinkedHashSet<>();
    final Set<String> propertyNames = new LinkedHashSet<>();
    final Set<String> relationshipPropertyNames = new LinkedHashSet<>();
    final Set<Validator> validators = new LinkedHashSet<>();
    final Set<String> implementedInterfaces = new LinkedHashSet<>();
    final List<String> importStatements = new LinkedList<>();
    final Set<String> enums = new LinkedHashSet<>();
    final StringBuilder src = new StringBuilder();
    final StringBuilder mixinCodeBuffer = new StringBuilder();
    final Class baseType = AbstractNode.class;
    final String _className = schemaNode.getProperty(SchemaNode.name);
    final String _extendsClass = schemaNode.getProperty(SchemaNode.extendsClass);
    final String superClass = _extendsClass != null ? _extendsClass : baseType.getSimpleName();
    final boolean extendsAbstractNode = _extendsClass == null;
    // check superclass
    if (!extendsAbstractNode && !superClass.startsWith("org.structr.dynamic.") && !SchemaHelper.hasType(superClass)) {
        // we can only detect if a type is missing that is usually provided by a module; we
        // can not detect whether a dynamic type is missing because those are only available
        // after compiling the whole set of schema nodes
        logger.warn("Dynamic type {} cannot be used, superclass {} not defined.", schemaNode.getName(), superClass);
        return null;
    }
    // import mixins, check that all types exist and return null otherwise (causing this class to be ignored)
    SchemaHelper.collectInterfaces(schemaNode, implementedInterfaces);
    // package name
    src.append("package org.structr.dynamic;\n\n");
    // include import statements from mixins
    SchemaHelper.formatImportStatements(schemaNode, src, baseType, importStatements);
    if (schemaNode.getProperty(SchemaNode.isInterface)) {
        // create interface
        src.append("public interface ");
        src.append(_className);
        // output implemented interfaces
        if (!implementedInterfaces.isEmpty()) {
            src.append(" extends ");
            src.append(StringUtils.join(implementedInterfaces, ", "));
        }
    } else {
        // create class
        src.append("public ");
        if (schemaNode.getProperty(SchemaNode.isAbstract)) {
            src.append("abstract ");
        }
        src.append("class ");
        src.append(_className);
        src.append(" extends ");
        src.append(superClass);
        // output implemented interfaces
        if (!implementedInterfaces.isEmpty()) {
            src.append(" implements ");
            src.append(StringUtils.join(implementedInterfaces, ", "));
        }
    }
    src.append(" {\n\n");
    // output related node definitions, collect property views
    for (final SchemaRelationshipNode outRel : schemaNode.getProperty(SchemaNode.relatedTo)) {
        final String propertyName = outRel.getPropertyName(_className, existingPropertyNames, true);
        propertyNames.add(propertyName);
        src.append(outRel.getPropertySource(propertyName, true));
        // schema changes are expected to be added to "ui" view.
        if (!outRel.getProperty(SchemaRelationshipNode.isPartOfBuiltInSchema)) {
            addPropertyToView(PropertyView.Ui, propertyName, viewProperties);
        }
        relationshipPropertyNames.add(propertyName);
    }
    // output related node definitions, collect property views
    for (final SchemaRelationshipNode inRel : schemaNode.getProperty(SchemaNode.relatedFrom)) {
        final String propertyName = inRel.getPropertyName(_className, existingPropertyNames, false);
        propertyNames.add(propertyName);
        src.append(inRel.getPropertySource(propertyName, false));
        // schema changes are expected to be added to "ui" view.
        if (!inRel.getProperty(SchemaRelationshipNode.isPartOfBuiltInSchema)) {
            SchemaHelper.addPropertyToView(PropertyView.Ui, propertyName, viewProperties);
        }
        relationshipPropertyNames.add(propertyName);
    }
    src.append(SchemaHelper.extractProperties(schemaNode, propertyNames, validators, compoundIndexKeys, enums, viewProperties, propertyValidators, errorBuffer));
    SchemaHelper.extractViews(schemaNode, viewProperties, relationshipPropertyNames, errorBuffer);
    SchemaHelper.extractMethods(schemaNode, methods);
    // output possible enum definitions
    for (final String enumDefition : enums) {
        src.append(enumDefition);
    }
    for (Entry<String, Set<String>> entry : viewProperties.entrySet()) {
        final String viewName = entry.getKey();
        final Set<String> view = entry.getValue();
        if (!view.isEmpty()) {
            schemaNode.addDynamicView(viewName);
            SchemaHelper.formatView(src, _className, viewName, viewName, view);
        }
    }
    if (schemaNode.getProperty(defaultSortKey) != null) {
        String order = schemaNode.getProperty(defaultSortOrder);
        if (order == null || "desc".equals(order)) {
            order = "GraphObjectComparator.DESCENDING";
        } else {
            order = "GraphObjectComparator.ASCENDING";
        }
        src.append("\n\t@Override\n");
        src.append("\tpublic PropertyKey getDefaultSortKey() {\n");
        src.append("\t\treturn ").append(schemaNode.getProperty(defaultSortKey)).append("Property;\n");
        src.append("\t}\n");
        src.append("\n\t@Override\n");
        src.append("\tpublic String getDefaultSortOrder() {\n");
        src.append("\t\treturn ").append(order).append(";\n");
        src.append("\t}\n");
    }
    SchemaHelper.formatValidators(src, validators, compoundIndexKeys, extendsAbstractNode, propertyValidators);
    SchemaHelper.formatMethods(schemaNode, src, methods, implementedInterfaces);
    // insert dynamic code here
    src.append(mixinCodeBuffer);
    // insert source code from module
    for (final StructrModule module : modules) {
        module.insertSourceCode(schemaNode, src);
    }
    src.append("}\n");
    return src.toString();
}
Also used : App(org.structr.core.app.App) StructrApp(org.structr.core.app.StructrApp) LinkedHashSet(java.util.LinkedHashSet) Set(java.util.Set) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) AbstractNode(org.structr.core.entity.AbstractNode) LinkedList(java.util.LinkedList) LinkedHashMap(java.util.LinkedHashMap) StructrModule(org.structr.module.StructrModule) SchemaRelationshipNode(org.structr.core.entity.SchemaRelationshipNode) List(java.util.List) LinkedList(java.util.LinkedList) Validator(org.structr.schema.parser.Validator)

Example 77 with App

use of org.structr.core.app.App in project structr by structr.

the class SchemaHelper method extractMethods.

public static void extractMethods(final AbstractSchemaNode entity, final Map<String, List<ActionEntry>> actions) throws FrameworkException {
    final PropertyContainer propertyContainer = entity.getPropertyContainer();
    for (final String rawActionName : getActions(propertyContainer)) {
        if (propertyContainer.hasProperty(rawActionName)) {
            final String value = propertyContainer.getProperty(rawActionName).toString();
            if (entity instanceof AbstractSchemaNode) {
                final AbstractSchemaNode schemaNode = (AbstractSchemaNode) entity;
                final App app = StructrApp.getInstance();
                final String methodName = rawActionName.substring(3);
                if (app.nodeQuery(SchemaMethod.class).and(SchemaMethod.schemaNode, schemaNode).and(AbstractNode.name, methodName).getFirst() == null) {
                    app.create(SchemaMethod.class, new NodeAttribute<>(SchemaMethod.schemaNode, schemaNode), new NodeAttribute<>(SchemaMethod.name, methodName), new NodeAttribute<>(SchemaMethod.source, value));
                    schemaNode.removeProperty(new StringProperty(rawActionName));
                }
            }
        }
    }
    final List<SchemaMethod> schemaMethods = entity.getSchemaMethods();
    if (schemaMethods != null) {
        for (final SchemaMethod schemaMethod : schemaMethods) {
            final ActionEntry entry = schemaMethod.getActionEntry(entity);
            final String name = entry.getName();
            List<ActionEntry> actionList = actions.get(name);
            if (actionList == null) {
                actionList = new LinkedList<>();
                actions.put(name, actionList);
            }
            actionList.add(entry);
            Collections.sort(actionList);
        }
    }
}
Also used : App(org.structr.core.app.App) StructrApp(org.structr.core.app.StructrApp) PropertyContainer(org.structr.api.graph.PropertyContainer) ActionEntry(org.structr.schema.action.ActionEntry) SchemaMethod(org.structr.core.entity.SchemaMethod) AbstractSchemaNode(org.structr.core.entity.AbstractSchemaNode) StringProperty(org.structr.core.property.StringProperty)

Example 78 with App

use of org.structr.core.app.App in project structr by structr.

the class SchemaHelper method extractViews.

public static void extractViews(final Schema entity, final Map<String, Set<String>> views, final Set<String> relPropertyNames, final ErrorBuffer errorBuffer) throws FrameworkException {
    final PropertyContainer propertyContainer = entity.getPropertyContainer();
    final ConfigurationProvider config = StructrApp.getConfiguration();
    Class superClass = config.getNodeEntityClass(entity.getSuperclassName());
    if (superClass == null) {
        superClass = config.getRelationshipEntityClass(entity.getSuperclassName());
    }
    if (superClass == null) {
        superClass = AbstractNode.class;
    }
    for (final String rawViewName : getViews(propertyContainer)) {
        if (!rawViewName.startsWith("___") && propertyContainer.hasProperty(rawViewName)) {
            final String value = propertyContainer.getProperty(rawViewName).toString();
            final String[] parts = value.split("[,\\s]+");
            final String viewName = rawViewName.substring(2);
            if (entity instanceof AbstractSchemaNode) {
                final List<String> nonGraphProperties = new LinkedList<>();
                final List<SchemaProperty> properties = new LinkedList<>();
                final AbstractSchemaNode schemaNode = (AbstractSchemaNode) entity;
                final App app = StructrApp.getInstance();
                if (app.nodeQuery(SchemaView.class).and(SchemaView.schemaNode, schemaNode).and(AbstractNode.name, viewName).getFirst() == null) {
                    // add parts to view, overrides defaults (because of clear() above)
                    for (int i = 0; i < parts.length; i++) {
                        String propertyName = parts[i].trim();
                        while (propertyName.startsWith("_")) {
                            propertyName = propertyName.substring(1);
                        }
                        // append this as a workaround to include remote properties
                        if (propertyName.endsWith("Property")) {
                            propertyName = propertyName.substring(0, propertyName.length() - "Property".length());
                        }
                        final SchemaProperty propertyNode = app.nodeQuery(SchemaProperty.class).and(SchemaProperty.schemaNode, schemaNode).andName(propertyName).getFirst();
                        if (propertyNode != null) {
                            properties.add(propertyNode);
                        } else {
                            nonGraphProperties.add(propertyName);
                        }
                    }
                    app.create(SchemaView.class, new NodeAttribute<>(SchemaView.schemaNode, schemaNode), new NodeAttribute<>(SchemaView.schemaProperties, properties), new NodeAttribute<>(SchemaView.name, viewName), new NodeAttribute<>(SchemaView.nonGraphProperties, StringUtils.join(nonGraphProperties, ",")));
                    schemaNode.removeProperty(new StringProperty(rawViewName));
                }
            }
        }
    }
    final List<SchemaView> schemaViews = entity.getSchemaViews();
    if (schemaViews != null) {
        for (final SchemaView schemaView : schemaViews) {
            final String nonGraphProperties = schemaView.getProperty(SchemaView.nonGraphProperties);
            final String viewName = schemaView.getName();
            // clear view before filling it again
            Set<String> view = views.get(viewName);
            if (view == null) {
                view = new LinkedHashSet<>();
                views.put(viewName, view);
            }
            final List<SchemaProperty> schemaProperties = schemaView.getProperty(SchemaView.schemaProperties);
            for (final SchemaProperty property : schemaProperties) {
                if (property.getProperty(SchemaProperty.isBuiltinProperty) && !property.getProperty(SchemaProperty.isDynamic)) {
                    view.add(SchemaHelper.cleanPropertyName(property.getPropertyName()));
                } else {
                    view.add(SchemaHelper.cleanPropertyName(property.getPropertyName() + "Property"));
                }
            }
            // add properties that are not part of the graph
            if (StringUtils.isNotBlank(nonGraphProperties)) {
                for (final String propertyName : nonGraphProperties.split("[, ]+")) {
                    if (SchemaHelper.isDynamic(entity.getClassName(), propertyName)) {
                        view.add(SchemaHelper.cleanPropertyName(propertyName + "Property"));
                    } else if (relPropertyNames.contains(propertyName)) {
                        view.add(SchemaHelper.cleanPropertyName(propertyName) + "Property");
                    } else if (basePropertyNames.contains(propertyName)) {
                        view.add(SchemaHelper.cleanPropertyName(propertyName));
                    } else {
                        logger.warn("Unknown property {} in non-graph properties, ignoring.", propertyName);
                        SchemaHelper.isDynamic(entity.getClassName(), propertyName);
                    }
                }
            }
            final String order = schemaView.getProperty(SchemaView.sortOrder);
            if (order != null) {
                applySortOrder(view, order);
            }
        }
    }
}
Also used : App(org.structr.core.app.App) StructrApp(org.structr.core.app.StructrApp) PropertyContainer(org.structr.api.graph.PropertyContainer) SchemaProperty(org.structr.core.entity.SchemaProperty) StringProperty(org.structr.core.property.StringProperty) LinkedList(java.util.LinkedList) SchemaView(org.structr.core.entity.SchemaView) AbstractSchemaNode(org.structr.core.entity.AbstractSchemaNode)

Example 79 with App

use of org.structr.core.app.App 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)

Example 80 with App

use of org.structr.core.app.App in project structr by structr.

the class ActionContext method getJavascriptLibraryCode.

public String getJavascriptLibraryCode(String fileName) {
    synchronized (libraryCache) {
        String cachedSource = libraryCache.get(fileName);
        if (cachedSource == null) {
            final StringBuilder buf = new StringBuilder();
            final App app = StructrApp.getInstance();
            try (final Tx tx = app.tx()) {
                final List<JavaScriptSource> jsFiles = app.nodeQuery(JavaScriptSource.class).and(JavaScriptSource.name, fileName).and(StructrApp.key(JavaScriptSource.class, "useAsJavascriptLibrary"), true).getAsList();
                if (jsFiles.isEmpty()) {
                    logger.warn("No JavaScript library file found with fileName: {}", fileName);
                } else if (jsFiles.size() > 1) {
                    logger.warn("Multiple JavaScript library files found with fileName: {}. This may cause problems!", fileName);
                }
                for (final JavaScriptSource jsLibraryFile : jsFiles) {
                    final String contentType = jsLibraryFile.getContentType();
                    if (contentType != null) {
                        final String lowerCaseContentType = contentType.toLowerCase();
                        if ("text/javascript".equals(lowerCaseContentType) || "application/javascript".equals(lowerCaseContentType)) {
                            buf.append(jsLibraryFile.getJavascriptLibraryCode());
                        } else {
                            logger.info("Ignoring file {} for use as a Javascript library, content type {} not allowed. Use text/javascript or application/javascript.", new Object[] { jsLibraryFile.getName(), contentType });
                        }
                    } else {
                        logger.info("Ignoring file {} for use as a Javascript library, content type not set. Use text/javascript or application/javascript.", new Object[] { jsLibraryFile.getName(), contentType });
                    }
                }
                tx.success();
            } catch (FrameworkException fex) {
                logger.warn("", fex);
            }
            cachedSource = buf.toString();
            libraryCache.put(fileName, cachedSource);
        }
        return cachedSource;
    }
}
Also used : StructrApp(org.structr.core.app.StructrApp) App(org.structr.core.app.App) Tx(org.structr.core.graph.Tx) FrameworkException(org.structr.common.error.FrameworkException)

Aggregations

App (org.structr.core.app.App)296 StructrApp (org.structr.core.app.StructrApp)294 Tx (org.structr.core.graph.Tx)201 FrameworkException (org.structr.common.error.FrameworkException)176 LinkedList (java.util.LinkedList)60 SecurityContext (org.structr.common.SecurityContext)56 PropertyMap (org.structr.core.property.PropertyMap)41 Folder (org.structr.web.entity.Folder)38 GraphObject (org.structr.core.GraphObject)35 Principal (org.structr.core.entity.Principal)31 IOException (java.io.IOException)30 AbstractFile (org.structr.web.entity.AbstractFile)27 AbstractNode (org.structr.core.entity.AbstractNode)26 Test (org.junit.Test)24 NodeAttribute (org.structr.core.graph.NodeAttribute)24 File (org.structr.web.entity.File)23 NodeInterface (org.structr.core.graph.NodeInterface)22 SchemaNode (org.structr.core.entity.SchemaNode)19 PropertyKey (org.structr.core.property.PropertyKey)17 Map (java.util.Map)16