1   /**
2    * Distribution License:
3    * JSword is free software; you can redistribute it and/or modify it under
4    * the terms of the GNU Lesser General Public License, version 2.1 or later
5    * as published by the Free Software Foundation. This program is distributed
6    * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
7    * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
8    * See the GNU Lesser General Public License for more details.
9    *
10   * The License is available on the internet at:
11   *      http://www.gnu.org/copyleft/lgpl.html
12   * or by writing to:
13   *      Free Software Foundation, Inc.
14   *      59 Temple Place - Suite 330
15   *      Boston, MA 02111-1307, USA
16   *
17   * © CrossWire Bible Society, 2007 - 2016
18   *
19   */
20  package org.crosswire.common.diff;
21  
22  /**
23   * Computes the difference between two texts to create a patch. Applies the
24   * patch onto another text, allowing for errors.
25   * 
26   * Based on the LGPL Diff_Match_Patch v1.5 javascript of Neil Fraser, Copyright (C) 2006<br>
27   * <a href="http://neil.fraser.name/software/diff_match_patch/">http://neil.fraser.name/software/diff_match_patch/</a>
28   * 
29   * @see gnu.lgpl.License The GNU Lesser General Public License for details.
30   * @author DM Smith
31   */
32  public class Match implements Locator {
33      public Match() {
34          this("", "", 0);
35      }
36  
37      /**
38       * Locate the best instance of 'pattern' in 'text' near 'loc'.
39       * 
40       * @param text
41       *            The text to search
42       * @param pattern
43       *            The pattern to search for
44       * @param loc
45       *            The location to search around
46       */
47      public Match(String text, String pattern, int loc) {
48          this.text = text;
49          this.pattern = pattern;
50          this.loc = loc;
51          this.locator = new Bitap(text, pattern, loc);
52      }
53  
54      /*
55       * (non-Javadoc)
56       * 
57       * @see org.crosswire.common.diff.Locator#maxPatternLength()
58       */
59      public int maxPatternLength() {
60          return locator.maxPatternLength();
61      }
62  
63      /**
64       * Locate the best instance of 'pattern' in 'text' near 'loc'.
65       * 
66       * @return Best match index or -1, if no match found
67       */
68      public int locate() {
69          if (text.equals(pattern)) {
70              // Shortcut (potentially not guaranteed by the algorithm)
71              return 0;
72          }
73  
74          if (text.length() == 0) {
75              // Nothing to match.
76              return -1;
77          }
78  
79          loc = Math.max(0, Math.min(loc, text.length() - pattern.length()));
80          if (text.substring(loc, loc + pattern.length()).equals(pattern)) {
81              // Perfect match at the perfect spot! (Includes case of null
82              // pattern)
83              return loc;
84          }
85  
86          return locator.locate();
87      }
88  
89      /**
90       * The text to search.
91       */
92      private String text;
93  
94      /**
95       * The pattern to find in the text.
96       */
97      private String pattern;
98  
99      /**
100      * The location in text to focus the search.
101      */
102     private int loc;
103 
104     /**
105      * The strategy for locating a best match.
106      */
107     private Locator locator;
108 }
109