docs: @SuppressWarnings("unchecked")
    private void init(SolrQueryRequest req) throws IOException {
      if (config == null) {
        // initialise
        config = new MtasUpdateRequestProcessorConfig();
        // required info
        Map<String, FieldType> fieldTypes = req.getSchema().getFieldTypes();
        Map<String, SchemaField> fields = req.getSchema().getFields();
        SolrResourceLoader resourceLoader = req.getCore().getSolrConfig()
            .getResourceLoader();
        // check fieldTypes
        // for (String name : fieldTypes.keySet()) {
        for (Entry<String, FieldType> entry : fieldTypes.entrySet()) {
          // only for MtasPreAnalyzedField
          if (entry.getValue() instanceof MtasPreAnalyzedField) {
            MtasPreAnalyzedField mpaf = (MtasPreAnalyzedField) entry.getValue();
            config.fieldTypeDefaultConfiguration.put(entry.getKey(),
                mpaf.defaultConfiguration);
            config.fieldTypeConfigurationFromField.put(entry.getKey(),
                mpaf.configurationFromField);
            config.fieldTypeNumberOfTokensField.put(entry.getKey(),
                mpaf.setNumberOfTokens);
            config.fieldTypeNumberOfPositionsField.put(entry.getKey(),
                mpaf.setNumberOfPositions);
            config.fieldTypeSizeField.put(entry.getKey(), mpaf.setSize);
            config.fieldTypeErrorField.put(entry.getKey(), mpaf.setError);
            config.fieldTypePrefixField.put(entry.getKey(), mpaf.setPrefix);
            config.fieldTypePrefixNumbersFieldPrefix.put(entry.getKey(), mpaf.setPrefixNumbers);
            if (mpaf.followIndexAnalyzer == null
                || !fieldTypes.containsKey(mpaf.followIndexAnalyzer)) {
              throw new IOException(
                  entry.getKey() + " can't follow " + mpaf.followIndexAnalyzer);
            } else {
              FieldType fieldType = fieldTypes.get(mpaf.followIndexAnalyzer);
              SimpleOrderedMap<?> analyzer = null;
              Object tmpObj1 = fieldType.getNamedPropertyValues(false)
                  .get(FieldType.INDEX_ANALYZER);
              if (tmpObj1 != null && tmpObj1 instanceof SimpleOrderedMap) {
                analyzer = (SimpleOrderedMap<?>) tmpObj1;
              }
              if (analyzer == null) {
                Object tmpObj2 = fieldType.getNamedPropertyValues(false)
                    .get(FieldType.ANALYZER);
                if (tmpObj2 != null && tmpObj2 instanceof SimpleOrderedMap) {
                  analyzer = (SimpleOrderedMap<?>) tmpObj2;
                }
              }
              if (analyzer == null) {
                throw new IOException("no analyzer");
              } else {
                // charfilters
                ArrayList<SimpleOrderedMap<Object>> listCharFilters = null;
                SimpleOrderedMap<Object> configTokenizer = null;
                try {
                  listCharFilters = (ArrayList<SimpleOrderedMap<Object>>) analyzer
                      .findRecursive(FieldType.CHAR_FILTERS);
                  ;
                  configTokenizer = (SimpleOrderedMap<Object>) analyzer
                      .findRecursive(FieldType.TOKENIZER);
                } catch (ClassCastException e) {
                  throw new IOException(
                      "could not cast charFilters and/or tokenizer from analyzer",
                      e);
                }
                if (listCharFilters != null && !listCharFilters.isEmpty()) {
                  CharFilterFactory[] charFilterFactories = new CharFilterFactory[listCharFilters
                      .size()];
                  int number = 0;
                  for (SimpleOrderedMap<Object> configCharFilter : listCharFilters) {
                    String className = null;
                    Map<String, String> args = new HashMap<>();
                    Iterator<Map.Entry<String, Object>> it = configCharFilter
                        .iterator();
                    // get className and args
                    while (it.hasNext()) {
                      Map.Entry<String, Object> obj = it.next();
                      if (obj.getValue() instanceof String) {
                        if (obj.getKey().equals(FieldType.CLASS_NAME)) {
                          className = (String) obj.getValue();
                        } else {
                          args.put(obj.getKey(), (String) obj.getValue());
                        }
                      }
                    }
                    if (className != null) {
                      try {
                        Class<?> cls = Class.forName((String) className);
                        if (cls.isAssignableFrom(MtasCharFilterFactory.class)) {
                          Class<?>[] types = { Map.class, ResourceLoader.class };
                          Constructor<?> cnstr = cls.getConstructor(types);
                          Object cff = cnstr.newInstance(args, resourceLoader);
                          if (cff instanceof MtasCharFilterFactory) {
                            charFilterFactories[number] = (MtasCharFilterFactory) cff;
                            number++;
                          } else {
                            throw new IOException(
                                className + " is no MtasCharFilterFactory");
                          }
                        } else {
                          Class<?>[] types = { Map.class };
                          Constructor<?> cnstr = cls.getConstructor(types);
                          Object cff = cnstr.newInstance(args);
                          if (cff instanceof CharFilterFactory) {
                            charFilterFactories[number] = (CharFilterFactory) cff;
                            number++;
                          } else {
                            throw new IOException(
                                className + " is no CharFilterFactory");
                          }
                        }
                      } catch (ClassNotFoundException | InstantiationException
                          | IllegalAccessException | IllegalArgumentException
                          | InvocationTargetException | NoSuchMethodException e) {
                        throw new IOException(e);
                      }
                    } else {
                      throw new IOException("no className");
                    }
                  }
                  config.fieldTypeCharFilterFactories.put(entry.getKey(),
                      charFilterFactories);
                } else {
                  config.fieldTypeCharFilterFactories.put(entry.getKey(), null);
                }
                if (configTokenizer != null) {
                  String className = null;
                  Map<String, String> args = new HashMap<>();
                  Iterator<Map.Entry<String, Object>> it = configTokenizer
                      .iterator();
                  // get className and args
                  while (it.hasNext()) {
                    Map.Entry<String, Object> obj = it.next();
                    if (obj.getValue() instanceof String) {
                      if (obj.getKey().equals(FieldType.CLASS_NAME)) {
                        className = (String) obj.getValue();
                      } else {
                        args.put(obj.getKey(), (String) obj.getValue());
                      }
                    }
                  }
                  if (className != null) {
                    try {
                      Class<?> cls = Class.forName((String) className);
                      Class<?>[] types = { Map.class, ResourceLoader.class };
                      Constructor<?> cnstr = cls.getConstructor(types);
                      Object cff = cnstr.newInstance(args, resourceLoader);
                      if (cff instanceof MtasTokenizerFactory) {
                        config.fieldTypeTokenizerFactory.put(entry.getKey(),
                            (MtasTokenizerFactory) cff);
                      } else {
                        throw new IOException(
                            className + " is no MtasTokenizerFactory");
                      }
                    } catch (ClassNotFoundException | InstantiationException
                        | IllegalAccessException | IllegalArgumentException
                        | InvocationTargetException | NoSuchMethodException e) {
                      throw new IOException(e);
                    }
                  } else {
                    throw new IOException("no className");
                  }
                }
  
              }
            }
          }
        }
        for (Entry<String, SchemaField> entry : fields.entrySet()) {
          if (entry.getValue().getType() != null
              && config.fieldTypeTokenizerFactory
                  .containsKey(entry.getValue().getType().getTypeName())) {
            config.fieldMapping.put(entry.getKey(),
                entry.getValue().getType().getTypeName());
          }
        }
      }
    }