Package ketUI.modes

Source Code of ketUI.modes.Search

/*
* Copyright (C) 2011  Alasdair C. Hamilton
*
* This program 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.
*
* This program 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 this program.  If not, see <http://www.gnu.org/licenses/>
*/

package ketUI.modes;

import java.util.*;

import ket.*;
import ket.math.*;
import ket.math.convert.ArgumentParser;
import ketUI.Clipboard;
import ketUI.Document;

public class Search {
  public static final boolean FORWARDS = false;
  public static final boolean BACKWARDS = true;

  // TODO: Use dependency injection as its value changes dynamically.
  final Clipboard clipboard;
  final KnownArguments knownArguments;
  final Modes modes;

  LoopIterator<Argument> searchMatches;
  String pattern;
  boolean direction;

  public Search(KnownArguments knownArguments, Clipboard clipboard, Modes modes) {
    this.knownArguments = knownArguments;
    this.clipboard = clipboard;
    this.modes = modes;
    this.searchMatches = null;
  }

  /**
   * Search for a given argument/symbol/branch pattern within the current
   * equationList, starting from the current argument.
   *  
   * @param pattern A string representation of a pattern of an argument,
   * or equation sub-branch, to denote the sought particular.
   * @param direction Set this variable to <I>true</I> in order to search the list of equations backwards (upwards).
   * @return If the search finds one or more matches then true is returned.
   */
  public boolean search(String pattern, boolean direction) {
    this.pattern = pattern;
    this.direction = direction;
    Vector<Argument> matches = new Vector<Argument>();
    Integer index = null;
    Address currentAddress = getCurrent().getAddress();
    Argument parsedPattern = parsePattern(pattern);
    Function charFunction = getFunctionByChar(pattern);
    //- boolean before = true;
    //- boolean after = false;
    for (Equation equation : getSelection().getEquationList().getEquations()) {
      Argument root = equation.getRoot();
      Vector<Argument> argsVector = new ArgumentVector(root, ArgumentVector.INCLUDE_ROOT);
      for (Argument argument : argsVector) {
        /*- if (before && !currentAddress.follows(argument)) {
          before = false;
        }
        if (!after && currentAddress.precedes(argument)) {
          after = true;
        } */
        if ( ! isMatch(argument, parsedPattern, pattern, charFunction) ) {
          continue;
        }
        if (direction==FORWARDS && !currentAddress.precedes(argument)) {
          index = matches.size() + 1;
        } else if (index==null && !currentAddress.follows(argument)) {
          index = matches.size() - 2;
        }
        matches.add(argument);
      }
    }
    if (matches.size()==0) {
      return false;
    }
    if (index==null) {
      index=0;
    }
    searchMatches = new LoopIterator<Argument>(matches, index, direction);
    if (direction==FORWARDS) {
      getNextMatch();
    } else {
      getPreviousMatch();
    }
    return true;
  }

  public boolean searchAgain() {
    if (this.pattern==null) return false;
    return search(this.pattern, this.direction);
  }

  public boolean searchAgainst() {
    if (this.pattern==null) return false;
    return search(this.pattern, !this.direction);
  }

  /**
   * If the search pattern is one of a predefined set of characters,
   * return the corresponding function and null otherwise.
   */
  private Function getFunctionByChar(String pattern) {
    String trimmedPattern = pattern.trim();
    Function charFunction = null;
    if (trimmedPattern.length()!=1) {
      return null;
    }
    char c = trimmedPattern.charAt(0);
    return knownArguments.getFunctionByChar(c);
  }

  private boolean isMatch(Argument argument, Argument parsedPattern, String pattern, Function charFunction) {
    State searchState = parsedPattern.getState();
    Symbol searchSymbol = searchState instanceof Symbol ? (Symbol) searchState : null;
    if (argument.matches(pattern)) {
      // An explicit match by name or by value.
      // TODO: Is this to general for branches: their
      // children are ignored and can match tokens?
      return true;
    } else if (parsedPattern==null) {
      return false;
    } else if (argument.subBranchEquals(parsedPattern)) {
      return true;
    } else if (charFunction!=null) {
      if (argument.getFunction()==charFunction) {
        return true;
      }
    }

    Purpose argumentPurpose = argument.getPurpose();
    if (searchSymbol==null) {
      return false;
    }
    if (argumentPurpose==null) {
      return false;
    }
    Set<Symbol> set = argumentPurpose.getMatchSymbols();
    return set.contains(searchSymbol);
  }

  private Argument parsePattern(String pattern) {
    Document document = modes.getDocument();
    MathCollection mathCollection = document.getMathCollection();
    return ArgumentParser.parseArgument(pattern, knownArguments, clipboard, mathCollection);
  }

  private void moveTo(Argument argument) { // TODO: Simplify
    assert argument != null;
    //- if (argument!=null) { //?
      getSelection().setCurrent(argument);
    //- }
  }

  private Argument getNextMatch() {
    if (searchMatches==null) {
      return null;
    }
    Argument nextArgument = searchMatches.next();
    moveTo(nextArgument);
    return nextArgument;
  }

  private Argument getPreviousMatch() {
    if (searchMatches==null) {
      return null;
    }
    Argument previousArgument = searchMatches.previous();
    moveTo(previousArgument);
    return previousArgument;
  }

  public Vector<Equation> getEquationMatches() {
    if (searchMatches==null) {
      return null;
    }
    Vector<Argument> args = searchMatches.getArgs();
    Vector<Equation> equations = new Vector<Equation>();
    for (Argument argument : args) {
      equations.add(argument.getEquation());
    }
    return equations;
  }

  private Selection getSelection() {
    return modes.getSelection();
  }

  private Argument getCurrent() {
    return getSelection().getCurrent();
  }

  public boolean hasMatch(Argument a) {
    if (a==null || searchMatches==null) return false;
    return a.isIn(searchMatches.getArgs());
  }

  public void searchBackwardsForCurrent() {
    modes.getSearch().search(getCurrent().toString(), Search.BACKWARDS);
  }
 
  public void searchForwardsForCurrent() {
    modes.getSearch().search(getCurrent().toString(), Search.FORWARDS);
  }
 
}
TOP

Related Classes of ketUI.modes.Search

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.