content: package org.apache.lucene.queryparser.flexible.aqp.processors;
  
  import org.apache.lucene.queryparser.flexible.aqp.nodes.AqpANTLRNode;
  import org.apache.lucene.queryparser.flexible.aqp.nodes.AqpFuzzyModifierNode;
  import org.apache.lucene.queryparser.flexible.aqp.parser.AqpStandardQueryConfigHandler;
  import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
  import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
  import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
  import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
  import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessor;
  import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessorImpl;
  import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
  
  import java.util.List;
  
  /**
   * Sets the node into the BoostQueryNode, this processor requires that
   * {@link AqpTMODIFIERProcessor} ran before. Because we depend on the proper
   * tree shape.
   *
   * <p>
   * <p>
   * If BOOST node contains only one child, we return that child and do nothing.
   *
   * <p>
   * <p>
   * If BOOST node contains two children, we take the first and check its input,
   * eg.
   *
   * <pre>
   *                  FUZZY
   *                  /  \
   *               ~0.1  rest
   * </pre>
   * <p>
   * We create a new node {@link AqpFuzzyModifierNode} (rest, 0.1) and
   * return that node.
   *
   * <p>
   * <p>
   * Presence of the BOOST node child means user specified at least "^" We'll use
   * the default from the configuration.
   *
   * @see AqpTMODIFIERProcessor
   * @see AqpFUZZYProcessor
   */
  public class AqpFUZZYProcessor extends QueryNodeProcessorImpl implements
          QueryNodeProcessor {
  
      @Override
      protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
          if (node instanceof AqpANTLRNode
                  && ((AqpANTLRNode) node).getTokenLabel().equals("FUZZY")) {
  
              if (node.getChildren().size() == 1) {
                  return node.getChildren().get(0);
              }
  
              Float fuzzy = getFuzzyValue(node);
  
              if (fuzzy == null) {
                  return node.getChildren().get(node.getChildren().size() - 1);
              }
  
              return new AqpFuzzyModifierNode(node.getChildren().get(
                      node.getChildren().size() - 1), fuzzy);
  
          }
          return node;
  
      }
  
      @Override
      protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
          return node;
      }
  
      @Override
      protected List<QueryNode> setChildrenOrder(List<QueryNode> children)
              throws QueryNodeException {
          return children;
      }
  
      private Float getFuzzyValue(QueryNode fuzzyNode) throws QueryNodeException {
          if (fuzzyNode.getChildren() != null) {
  
              AqpANTLRNode child = ((AqpANTLRNode) fuzzyNode.getChildren().get(0));
              String input = child.getTokenInput();
              float fuzzy;
  
              if (input.equals("~")) {
                  QueryConfigHandler queryConfig = getQueryConfigHandler();
                  if (queryConfig == null
                          || !queryConfig
                          .has(AqpStandardQueryConfigHandler.ConfigurationKeys.IMPLICIT_FUZZY)) {
                      throw new QueryNodeException(
                              new MessageImpl(
                                      QueryParserMessages.LUCENE_QUERY_CONVERSION_ERROR,
                                      "Configuration error: "
                                              + AqpStandardQueryConfigHandler.ConfigurationKeys.IMPLICIT_FUZZY + " is missing"));
                  }
                  fuzzy = queryConfig
                          .get(AqpStandardQueryConfigHandler.ConfigurationKeys.IMPLICIT_FUZZY);
              } else {
                  fuzzy = Float.valueOf(input.replace("~", ""));
              }
  
              return fuzzy;
  
          }
          return null;
      }
  
  }
  