Package org.structr.core.entity

Source Code of org.structr.core.entity.SchemaNode

/**
* Copyright (C) 2010-2014 Morgner UG (haftungsbeschränkt)
*
* This file is part of Structr <http://structr.org>.
*
* Structr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Structr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Structr.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.structr.core.entity;

import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.neo4j.helpers.collection.Iterables;
import org.structr.common.PropertyView;
import org.structr.common.Syncable;
import org.structr.common.ValidationHelper;
import org.structr.common.View;
import org.structr.common.error.ErrorBuffer;
import org.structr.common.error.FrameworkException;
import org.structr.core.entity.relationship.SchemaRelationship;
import org.structr.core.graph.NodeInterface;
import org.structr.core.graph.RelationshipInterface;
import org.structr.core.property.BooleanProperty;
import org.structr.core.property.EndNodes;
import org.structr.core.property.Property;
import org.structr.core.property.PropertyKey;
import org.structr.core.property.PropertyMap;
import org.structr.core.property.StartNodes;
import org.structr.core.property.StringProperty;
import org.structr.schema.Schema;
import org.structr.schema.SchemaHelper;
import org.structr.schema.SchemaNotion;
import org.structr.schema.action.ActionEntry;
import org.structr.schema.action.Actions;
import org.structr.schema.parser.Validator;

/**
*
* @author Christian Morgner
*/
public class SchemaNode extends AbstractSchemaNode implements Schema, Syncable {

  public static final Property<List<SchemaNode>>  relatedTo        = new EndNodes<>("relatedTo", SchemaRelationship.class, new SchemaNotion(SchemaNode.class));
  public static final Property<List<SchemaNode>>  relatedFrom      = new StartNodes<>("relatedFrom", SchemaRelationship.class, new SchemaNotion(SchemaNode.class));
  public static final Property<String>            extendsClass     = new StringProperty("extendsClass").indexed();
  public static final Property<String>            defaultSortKey   = new StringProperty("defaultSortKey");
  public static final Property<String>            defaultSortOrder = new StringProperty("defaultSortOrder");
  public static final Property<Boolean>           isBuiltinType    = new BooleanProperty("isBuiltinType").readOnly();

  public static final View defaultView = new View(SchemaNode.class, PropertyView.Public,
    name, extendsClass, relatedTo, relatedFrom, defaultSortKey, defaultSortOrder, isBuiltinType
  );

  public static final View uiView = new View(SchemaNode.class, PropertyView.Ui,
    name, extendsClass, relatedTo, relatedFrom, defaultSortKey, defaultSortOrder, isBuiltinType
  );

  private final Set<String> dynamicViews = new LinkedHashSet<>();

  @Override
  public Iterable<PropertyKey> getPropertyKeys(final String propertyView) {

    final List<PropertyKey> propertyKeys = new LinkedList<>(Iterables.toList(super.getPropertyKeys(propertyView)));

    // add "custom" property keys as String properties
    for (final String key : SchemaHelper.getProperties(getNode())) {

      final PropertyKey newKey = new StringProperty(key);
      newKey.setDeclaringClass(getClass());

      propertyKeys.add(newKey);
    }

    Collections.sort(propertyKeys, new Comparator<PropertyKey>() {

      @Override
      public int compare(PropertyKey o1, PropertyKey o2) {
        return o1.jsonName().compareTo(o2.jsonName());
      }
    });

    return new LinkedHashSet<>(propertyKeys);
  }

  @Override
  public String getSource(final ErrorBuffer errorBuffer) throws FrameworkException {

    final Map<Actions.Type, List<ActionEntry>> saveActions = new EnumMap<>(Actions.Type.class);
    final Map<String, Set<String>> viewProperties          = new LinkedHashMap<>();
    final Set<String> existingPropertyNames                = new LinkedHashSet<>();
    final Set<String> propertyNames                        = new LinkedHashSet<>();
    final Set<Validator> validators                        = new LinkedHashSet<>();
    final Set<String> enums                                = new LinkedHashSet<>();
    final StringBuilder src                                = new StringBuilder();
    final Class baseType                                   = AbstractNode.class;
    final String _className                                = getProperty(name);
    final String _extendsClass                             = getProperty(extendsClass);

    src.append("package org.structr.dynamic;\n\n");

    SchemaHelper.formatImportStatements(src, baseType);

    String superClass = _extendsClass != null ? _extendsClass : baseType.getSimpleName();

    src.append("public class ").append(_className).append(" extends ").append(superClass).append(" {\n\n");

    // output related node definitions, collect property views
    for (final SchemaRelationship outRel : getOutgoingRelationships(SchemaRelationship.class)) {

      final String propertyName = outRel.getPropertyName(_className, existingPropertyNames, true);

      //outRel.setProperty(SchemaRelationship.targetJsonName, propertyName);

      src.append(outRel.getPropertySource(propertyName, true));
      //existingPropertyNames.clear();
      addPropertyNameToViews(propertyName, viewProperties);

    }

    // output related node definitions, collect property views
    for (final SchemaRelationship inRel : getIncomingRelationships(SchemaRelationship.class)) {

      final String propertyName = inRel.getPropertyName(_className, existingPropertyNames, false);

      //inRel.setProperty(SchemaRelationship.sourceJsonName, propertyName);

      src.append(inRel.getPropertySource(propertyName, false));
      //existingPropertyNames.clear();
      addPropertyNameToViews(propertyName, viewProperties);

    }

    // extract properties from node
    src.append(SchemaHelper.extractProperties(this, propertyNames, validators, enums, viewProperties, saveActions, errorBuffer));

    // 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()) {
        dynamicViews.add(viewName);
        SchemaHelper.formatView(src, _className, viewName, viewName, view);
      }
    }

    if (getProperty(defaultSortKey) != null) {

      String order = 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(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);
    SchemaHelper.formatSaveActions(src, saveActions);

    src.append("}\n");

    return src.toString();
  }

  @Override
  public Set<String> getViews() {
    return dynamicViews;
  }

  @Override
  public boolean isValid(final ErrorBuffer errorBuffer) {

    return ValidationHelper.checkStringMatchesRegex(this, name, "[A-Z][a-zA-Z0-9_]+", errorBuffer);

  }

  @Override
  public String getMultiplicity(final String propertyNameToCheck) {

    final Set<String> existingPropertyNames = new LinkedHashSet<>();
    final String _className                 = getProperty(name);

    for (final SchemaRelationship outRel : getOutgoingRelationships(SchemaRelationship.class)) {

      if (propertyNameToCheck.equals(outRel.getPropertyName(_className, existingPropertyNames, true))) {
        return outRel.getMultiplicity(true);
      }
    }

    // output related node definitions, collect property views
    for (final SchemaRelationship inRel : getIncomingRelationships(SchemaRelationship.class)) {

      if (propertyNameToCheck.equals(inRel.getPropertyName(_className, existingPropertyNames, false))) {
        return inRel.getMultiplicity(false);
      }
    }

    return null;
  }

  @Override
  public String getRelatedType(final String propertyNameToCheck) {

    final Set<String> existingPropertyNames = new LinkedHashSet<>();
    final String _className                 = getProperty(name);

    for (final SchemaRelationship outRel : getOutgoingRelationships(SchemaRelationship.class)) {

      if (propertyNameToCheck.equals(outRel.getPropertyName(_className, existingPropertyNames, true))) {
        return outRel.getSchemaNodeTargetType();
      }
    }

    // output related node definitions, collect property views
    for (final SchemaRelationship inRel : getIncomingRelationships(SchemaRelationship.class)) {

      if (propertyNameToCheck.equals(inRel.getPropertyName(_className, existingPropertyNames, false))) {
        return inRel.getSchemaNodeSourceType();
      }
    }

    return null;
  }

  @Override
  public String getAuxiliarySource() throws FrameworkException {

    // only File needs to return auxiliary code!
    if (!"File".equals(getClassName())) {
      return null;
    }

    final Map<Actions.Type, List<ActionEntry>> saveActions = new EnumMap<>(Actions.Type.class);
    final Map<String, Set<String>> viewProperties          = new LinkedHashMap<>();
    final Set<String> propertyNames                        = new LinkedHashSet<>();
    final Set<Validator> validators                        = new LinkedHashSet<>();
    final Set<String> enums                                = new LinkedHashSet<>();
    final String _className                                = getProperty(name);
    final ErrorBuffer dummyErrorBuffer                     = new ErrorBuffer();

    // extract properties
    final String propertyDefinitions = SchemaHelper.extractProperties(this, propertyNames, validators, enums, viewProperties, saveActions, dummyErrorBuffer);

    if (!propertyNames.isEmpty() || validators.isEmpty() || !saveActions.isEmpty()) {

      final StringBuilder src = new StringBuilder();

      src.append("package org.structr.dynamic;\n\n");

      SchemaHelper.formatImportStatements(src, AbstractNode.class);

      src.append("public class _").append(_className).append("Helper {\n");

      // output possible enum definitions
      for (final String enumDefition : enums) {
        src.append(enumDefition);
      }

      // formatting is important :)
      if (!enums.isEmpty()) {
        src.append("\n");
      }

      if (!propertyNames.isEmpty()) {

        src.append("\n");

        // extract properties from node
        src.append(propertyDefinitions);

        src.append("\n\tstatic {\n\n");

        for (final String propertyName : propertyNames) {

          src.append("\t\t").append(propertyName).append(".setDeclaringClass(").append(_className).append(".class);\n\n");
          src.append("\t\tStructrApp.getConfiguration().registerDynamicProperty(").append(_className).append(".class, ").append(propertyName).append(");\n");
          src.append("\t\tStructrApp.getConfiguration().registerPropertySet(").append(_className).append(".class, PropertyView.Ui, ").append(propertyName).append(");\n\n");

        }

        src.append("\t}\n\n");
      }

      SchemaHelper.formatDynamicValidators(src, validators);
      SchemaHelper.formatDynamicSaveActions(src, saveActions);

      src.append("}\n");

      return src.toString();
    }

    return null;
  }

  // ----- private methods -----
  private void addPropertyNameToViews(final String propertyName, final Map<String, Set<String>> viewProperties) {
    //SchemaHelper.addPropertyToView(PropertyView.Public, propertyName, viewProperties);
    SchemaHelper.addPropertyToView(PropertyView.Ui, propertyName, viewProperties);
  }

  // ----- interface Syncable -----
  @Override
  public List<Syncable> getSyncData() {

    final List<Syncable> data = new LinkedList<>();

    // outgoing relationships
    for (final SchemaRelationship rel : getOutgoingRelationships(SchemaRelationship.class)) {
      data.add(rel);
    }

    // incoming relationships
    for (final SchemaRelationship rel : getIncomingRelationships(SchemaRelationship.class)) {
      data.add(rel);
    }

    return data;
  }

  @Override
  public boolean isNode() {
    return true;
  }

  @Override
  public boolean isRelationship() {
    return false;
  }

  @Override
  public NodeInterface getSyncNode() {
    return this;
  }

  @Override
  public RelationshipInterface getSyncRelationship() {
    return null;
  }

  @Override
  public void updateFromPropertyMap(final PropertyMap properties) throws FrameworkException {

    // update all properties that exist in the source map
    for (final Entry<PropertyKey, Object> entry : properties.entrySet()) {

      setProperty(entry.getKey(), entry.getValue());
    }
  }
}
TOP

Related Classes of org.structr.core.entity.SchemaNode

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.