protected MutableCachedNode createNode(
     SessionCache session,
     MutableCachedNode parent,
     String id,
     Name name,
     Name primaryType,
     Property... properties) {
   NodeKey key = session.getRootKey().withId(id);
   return parent.createChild(
       session, key, name, propFactory.create(JcrLexicon.PRIMARY_TYPE, primaryType), properties);
 }
 protected MutableCachedNode createNamespace(
     SessionCache session, MutableCachedNode parent, String prefix, String uri) {
   Name nodeName =
       prefix.length() != 0
           ? session.getContext().getValueFactories().getNameFactory().create(prefix)
           : ModeShapeLexicon.NAMESPACE;
   return createNode(
       session,
       parent,
       "mode:namespaces-" + uri,
       nodeName,
       ModeShapeLexicon.NAMESPACE,
       propFactory.create(ModeShapeLexicon.URI, uri),
       propFactory.create(ModeShapeLexicon.GENERATED, Boolean.FALSE));
 }
 @Override
 public boolean initializeIndexStorage(SessionCache session, MutableCachedNode systemNode) {
   this.propFactory = session.getContext().getPropertyFactory();
   assert systemNode != null;
   ChildReferences childReferences = systemNode.getChildReferences(session);
   // initializes the /jcr:system/mode:indexes node if not already present.
   NodeKey indexesNodeKey = systemNode.getKey().withId(INDEXES_NODE_ID);
   if (!childReferences.hasChild(indexesNodeKey)) {
     MutableCachedNode indexes =
         createNode(
             session,
             systemNode,
             INDEXES_NODE_ID,
             ModeShapeLexicon.INDEXES,
             ModeShapeLexicon.INDEXES);
     indexes.excludeFromSearch();
     return true;
   }
   return false;
 }
  @Override
  public void registerIndexes(IndexDefinition[] indexDefinitions, boolean allowUpdate)
      throws InvalidIndexDefinitionException, IndexExistsException {
    CheckArg.isNotNull(indexDefinitions, "indexDefinitions");

    // Before we do anything, validate each of the index definitions and throw an exception ...
    RepositoryNodeTypeManager nodeTypeManager = repository.nodeTypeManager();
    List<IndexDefinition> validated = new ArrayList<>(indexDefinitions.length);
    Problems problems = new SimpleProblems();
    for (IndexDefinition defn : indexDefinitions) {
      String name = defn.getName();
      String providerName = defn.getProviderName();

      if (name == null) {
        problems.addError(JcrI18n.indexMustHaveName, defn, repository.name());
        continue;
      }
      if (indexes.getIndexDefinitions().containsKey(name) && !allowUpdate) {
        // Throw this one immediately ...
        String msg = JcrI18n.indexAlreadyExists.text(defn.getName(), repository.name());
        throw new IndexExistsException(msg);
      }
      if (providerName == null) {
        problems.addError(JcrI18n.indexMustHaveProviderName, defn.getName(), repository.name());
        continue;
      }
      if (defn.hasSingleColumn()) {
        IndexColumnDefinition columnDefn = defn.getColumnDefinition(0);
        Name propName =
            context.getValueFactories().getNameFactory().create(columnDefn.getPropertyName());
        switch (defn.getKind()) {
          case UNIQUE_VALUE:
            if (NON_UNIQUE_PROPERTY_NAMES.contains(propName)) {
              problems.addError(
                  JcrI18n.unableToCreateUniqueIndexForColumn,
                  defn.getName(),
                  columnDefn.getPropertyName());
            }
            break;
          case ENUMERATED_VALUE:
            if (NON_ENUMERATED_PROPERTY_NAMES.contains(propName)) {
              problems.addError(
                  JcrI18n.unableToCreateEnumeratedIndexForColumn,
                  defn.getName(),
                  columnDefn.getPropertyName());
            }
            break;
          case VALUE:
          case NODE_TYPE:
          case TEXT:
            break;
        }
      } else {
        // Mulitple columns ...
        if (defn.getKind() == IndexKind.NODE_TYPE) {
          // must be single-column indexes
          problems.addError(JcrI18n.nodeTypeIndexMustHaveOneColumn, defn.getName());
        }
      }
      IndexProvider provider = providers.get(providerName);
      if (provider == null) {
        problems.addError(JcrI18n.indexProviderDoesNotExist, defn.getName(), repository.name());
      } else {
        // Perform some default validations that should be applied to all providers...
        provider.validateDefaultColumnTypes(context, defn, problems);

        // Then have the provider perform any custom validations
        provider.validateProposedIndex(context, defn, nodeTypeManager, problems);

        // Create an instance of our own definition implementation ...
        defn = RepositoryIndexDefinition.createFrom(defn, true);

        validated.add(defn);
      }
    }
    if (problems.hasErrors()) {
      String msg = JcrI18n.invalidIndexDefinitions.text(repository.name(), problems);
      throw new InvalidIndexDefinitionException(new JcrProblems(problems), msg);
    }

    SessionCache systemCache = repository.createSystemSession(context, false);
    SystemContent system = new SystemContent(systemCache);
    for (IndexDefinition defn : validated) {
      String providerName = defn.getProviderName();

      // Determine if the index should be enabled ...
      defn = RepositoryIndexDefinition.createFrom(defn, providers.containsKey(providerName));

      // Write the definition to the system area ...
      system.store(defn, allowUpdate);
    }
    // Save the changes ...
    systemCache.save();

    // Refresh the immutable snapshot ...
    this.indexes = readIndexDefinitions();
  }
  @Override
  public void initializeSystemArea(SessionCache session, MutableCachedNode parent) {
    this.propFactory = session.getContext().getPropertyFactory();
    MutableCachedNode system = null;
    MutableCachedNode namespaces = null;

    // Create the "/jcr:system" node ...
    system =
        createNode(session, parent, SYSTEM_NODE_ID, JcrLexicon.SYSTEM, ModeShapeLexicon.SYSTEM);

    // Create the "/jcr:system/jcr:nodeTypes" node ...
    createNode(
        session, system, "jcr:nodeTypes", JcrLexicon.NODE_TYPES, ModeShapeLexicon.NODE_TYPES);

    // Create the "/jcr:system/jcr:versionStorage" node which we don't want to index
    MutableCachedNode versionStorage =
        createNode(
            session,
            system,
            "jcr:versionStorage",
            JcrLexicon.VERSION_STORAGE,
            ModeShapeLexicon.VERSION_STORAGE);
    versionStorage.excludeFromSearch();

    // Create the "/jcr:system/mode:namespaces" node ...
    namespaces =
        createNode(
            session,
            system,
            "mode:namespaces",
            ModeShapeLexicon.NAMESPACES,
            ModeShapeLexicon.NAMESPACES);

    // Create the standard namespaces ...
    // createNamespace(session, namespaces, "", ""); // Don't initialize the "" namespaces
    createNamespace(session, namespaces, JcrLexicon.Namespace.PREFIX, JcrLexicon.Namespace.URI);
    createNamespace(session, namespaces, JcrNtLexicon.Namespace.PREFIX, JcrNtLexicon.Namespace.URI);
    createNamespace(
        session, namespaces, JcrMixLexicon.Namespace.PREFIX, JcrMixLexicon.Namespace.URI);
    createNamespace(session, namespaces, JcrSvLexicon.Namespace.PREFIX, JcrSvLexicon.Namespace.URI);
    createNamespace(
        session, namespaces, ModeShapeLexicon.Namespace.PREFIX, ModeShapeLexicon.Namespace.URI);
    createNamespace(
        session,
        namespaces,
        JcrNamespaceRegistry.XML_NAMESPACE_PREFIX,
        JcrNamespaceRegistry.XML_NAMESPACE_URI);
    createNamespace(
        session,
        namespaces,
        JcrNamespaceRegistry.XMLNS_NAMESPACE_PREFIX,
        JcrNamespaceRegistry.XMLNS_NAMESPACE_URI);
    createNamespace(
        session,
        namespaces,
        JcrNamespaceRegistry.XML_SCHEMA_NAMESPACE_PREFIX,
        JcrNamespaceRegistry.XML_SCHEMA_NAMESPACE_URI);
    createNamespace(
        session,
        namespaces,
        JcrNamespaceRegistry.XML_SCHEMA_INSTANCE_NAMESPACE_PREFIX,
        JcrNamespaceRegistry.XML_SCHEMA_INSTANCE_NAMESPACE_URI);

    // Create the "/jcr:system/mode:locks" node which we don't want to index
    MutableCachedNode locks =
        createNode(session, system, "mode:locks", ModeShapeLexicon.LOCKS, ModeShapeLexicon.LOCKS);
    locks.excludeFromSearch();

    // Create the "/jcr:system/mode:indexes" node which we don't want to index
    initializeIndexStorage(session, system);
  }