docs: @SuppressWarnings("unchecked")
      public ManagedIndex build() {
          List<IndexChangeAdapter> changeAdapters = new ArrayList<>();
          ProvidedIndex<?> index = null;
          switch (defn.getKind()) {
              case VALUE:
                  index = buildMultiValueIndex(context, defn, workspaceName, nodeTypesSupplier, matcher);
                  for (int i = 0; i < defn.size(); i++) {
                      IndexColumnDefinition columnDef = defn.getColumnDefinition(i);
                      PropertyType type = determineActualPropertyType(columnDef);
                      if (isPrimaryTypeIndex(columnDef, type)) {
                          changeAdapters.add(IndexChangeAdapters.forPrimaryType(context, matcher, workspaceName, index));
                      } else if (isMixinTypesIndex(columnDef, type)) {
                          changeAdapters.add(IndexChangeAdapters.forMixinTypes(context, matcher, workspaceName, index));
                      } else if (isNodeNameIndex(columnDef, type)) {
                          changeAdapters.add(IndexChangeAdapters.forNodeName(context, matcher, workspaceName, index));
                      } else if (isNodeLocalNameIndex(columnDef, type)) {
                          changeAdapters.add(IndexChangeAdapters.forNodeLocalName(context, matcher, workspaceName, index));
                      } else if (isNodePathIndex(columnDef, type)) {
                          changeAdapters.add(IndexChangeAdapters.forNodePath(context, matcher, workspaceName, index));
                      } else if (isNodeDepthIndex(columnDef, type)) {
                          changeAdapters.add(IndexChangeAdapters.forNodeDepth(context, matcher, workspaceName, index));
                      } else {
                          // This is a generic index for a property ...
                          Name propertyName = name(columnDef.getPropertyName());
                          assert propertyName != null;
  
                          ValueFactory<?> valueFactory = context.getValueFactories().getValueFactory(type);
                          changeAdapters.add(IndexChangeAdapters.forProperty(context, matcher, workspaceName, 
                                                                             propertyName, valueFactory, index));
                      }
                  } 
                  break;
              case UNIQUE_VALUE: 
                  index = buildUniqueValueIndex(context, defn, workspaceName, nodeTypesSupplier, matcher);
                  for (int i = 0; i < defn.size(); i++) {
                      IndexColumnDefinition columnDef = defn.getColumnDefinition(i);
                      PropertyType type = determineActualPropertyType(columnDef);
                      Name propertyName = name(columnDef.getPropertyName());
                      assert propertyName != null;
                      ValueFactory<?> valueFactory = context.getValueFactories().getValueFactory(type);
                      changeAdapters.add(IndexChangeAdapters.forUniqueValuedProperty(context, matcher, workspaceName,
                                                                                     propertyName,
                                                                                     valueFactory, index));
                  }
                  break;
              case ENUMERATED_VALUE:
                  index = buildEnumeratedIndex(context, defn, workspaceName, nodeTypesSupplier, matcher);
                  for (int i = 0; i < defn.size(); i++) {
                      IndexColumnDefinition columnDef = defn.getColumnDefinition(i);
                      Name propertyName = name(columnDef.getPropertyName());
                      assert propertyName != null;
                      changeAdapters.add(IndexChangeAdapters.forEnumeratedProperty(context, matcher, workspaceName,
                                                                                   propertyName, index));
                  }
                  break;
              case NODE_TYPE: 
                  index = buildNodeTypeIndex(context, defn, workspaceName, nodeTypesSupplier, matcher);
                  if (defn.size() > 1) {
                      throw new IllegalArgumentException("Cannot have a multi column node-type index");
                  }
                  String property = defn.getColumnDefinition(0).getPropertyName();
                  if (property == null) {
                      property = defn.getName();
                  }
                  changeAdapters.add(IndexChangeAdapters.forNodeTypes(property, context, matcher, workspaceName, index));
                  break;
              case TEXT: 
                  index = buildTextIndex(context, defn, workspaceName, nodeTypesSupplier, matcher);
                  ValueFactory<String> valueFactory = (ValueFactory<String>)context.getValueFactories().getValueFactory(PropertyType.STRING);
                  for (int i = 0; i < defn.size(); i++) {
                      IndexColumnDefinition columnDef = defn.getColumnDefinition(i);
                      PropertyType type = determineActualPropertyType(columnDef);
                      Name propertyName = name(columnDef.getPropertyName());
                      assert propertyName != null;
                      if (isNodeNameIndex(columnDef, type)) {
                          // FTS on jcr:name
                          changeAdapters.add(IndexChangeAdapters.forNodeName(context, matcher, workspaceName, index));
                      } else if (isNodeLocalNameIndex(columnDef, type)) {
                          // FTS on mode:localName
                          changeAdapters.add(IndexChangeAdapters.forNodeLocalName(context, matcher, workspaceName, index));
                      } else if (isNodePathIndex(columnDef, type)) {
                          // FTS on jcr:path
                          changeAdapters.add(IndexChangeAdapters.forNodePath(context, matcher, workspaceName, index));
                      } else {
                          // default to a property....
                          changeAdapters.add(IndexChangeAdapters.forTextProperty(context, matcher, workspaceName,
                                                                                 propertyName, valueFactory, index));
                      }
                  }
                  break;
              default: {
                  throw new IllegalArgumentException("Unexpected index kind on: " + defn);
              }
          }
          
          assert !changeAdapters.isEmpty();
          IndexChangeAdapter adapter = changeAdapters.size() == 1 ? 
                                       changeAdapters.get(0) :
                                       IndexChangeAdapters.forMultipleColumns(context, matcher, workspaceName, index,
                                                                              changeAdapters);
          return new DefaultManagedIndex(index, adapter);
      }