[
  {
    "path": ".github/workflows/gradle.yml",
    "content": "# This workflow will build a Java project with Gradle\n# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle\n\nname: Java CI with Gradle\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    steps:\n    - uses: actions/checkout@v2\n    - name: Set up JDK 1.8\n      uses: actions/setup-java@v1\n      with:\n        java-version: 1.8\n    - name: Grant execute permission for gradlew\n      run: chmod +x gradlew\n    - name: Build with Gradle\n      run: ./gradlew test\n"
  },
  {
    "path": ".gitignore",
    "content": "\n# General files\n*~\n*.lock\n*.DS_Store\n*.Trashes\n*.swp\n*.out\n*.bak\n\n# SVN\n.svn\n\n# Maven\n.m2\ntarget/\n\n# Eclipse\n.project\n.metadata\nbin/**\ntmp/**\ntmp/**/*\n.classpath\n.settings/\n.loadpath\nlocal.properties\n*~.nib\n*.launch\n.externalToolBuilders/\n\n# Intellij\n*.iml\n*.ipr\n*.iws\n.idea/\n\n# Netbeans\nnbproject/private/\nbuild/\nnbbuild/\ndist/\nnbdist/\nnbactions.xml\nnb-configuration.xml\n\n# Java \n*.class\n*.jar\n*.war\n*.ear\n*.db\n\n\n.gradle\n\n# Exceptions\n!/gradle/**\n"
  },
  {
    "path": ".travis.yml",
    "content": "\nlanguage: java\n\njdk:\n    - openjdk8\n    - openjdk10\n    - openjdk11\n\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE."
  },
  {
    "path": "README.md",
    "content": "\n[![License: MIT](https://img.shields.io/github/license/rrice/java-string-similarity)](https://opensource.org/licenses/MIT)\n[![Issues](https://img.shields.io/github/issues/rrice/java-string-similarity)](https://github.com/rrice/java-string-similarity/actions)\n![Java CI](https://github.com/rrice/java-string-similarity/workflows/Java%20CI%20with%20Gradle/badge.svg)\n\n\n[java-string-similarity](https://github.com/rrice/java-string-similarity) that calculates a normalized distance or similarity score between two strings. A score of 0.0 means that the two strings are absolutely dissimilar, and 1.0 means that absolutely similar (or equal). Anything in between indicates how similar each the two strings are.\n\nExample\n-------\n\nIn this simple example, we want to calculate a similarity score between the words `McDonalds` and `MacMahons`. We are selecting the [Jaro-Winkler distance algorithm](http://www.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance) algorithm.\n\n```java\nSimilarityStrategy strategy = new JaroWinklerStrategy();\nString target = \"McDonalds\";\nString source = \"MacMahons\";\nStringSimilarityService service = new StringSimilarityServiceImpl(strategy);\ndouble score = service.score(source, target); // Score is 0.90\n```\n\nAlgorithms\n----------\n\n* [Jaro distance](http://www.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance)\n* [Jaro-Winkler distance](http://www.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance)\n* [Levenshtein distance](http://www.wikipedia.org/wiki/Levenshtein_distance)\n* [Sørensen–Dice coefficient](http://www.wikipedia.org/wiki/Sørensen–Dice_coefficient)\n\n\nInstallation\n------------\n\nThis project currently uses [Maven](http://maven.apache.org/) for management. You can compile, test and install the component to your local repo by calling:\n\n```\nmvn install\n```\n\nThen, you can add this component to your project by adding a dependency:\n\n```\n<dependency>\n    <groupId>net.ricecode</groupId>\n\t<artifactId>string-similarity</artifactId>\n\t<version>1.0.0</version>\n</dependency>\n```\n\nTODO\n----\n\n* Ant/Ivy build scripts.\n\n* [Jaccard index](http://www.wikipedia.org/wiki/Jaccard_index)\n\n"
  },
  {
    "path": "build.gradle",
    "content": "apply plugin: 'java'\n\nrepositories {\n    mavenCentral()\n}\ndependencies {\n    testCompile 'junit:junit:4.+',\n                'org.mockito:mockito-all:1.9.5'\n}\n\n/*\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-4.10.2-bin.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=$(save \"$@\")\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\n# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong\nif [ \"$(uname)\" = \"Darwin\" ] && [ \"$HOME\" = \"$PWD\" ]; then\n  cd \"$(dirname \"$0\")\"\nfi\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windows variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>net.ricecode</groupId>\n\t<artifactId>string-similarity</artifactId>\n\t<version>1.0.1-SNAPSHOT</version>\n\t<packaging>jar</packaging>\n\n\t<name>string-similarity</name>\n\t<description>A Java library that implements several algorithms that calculate similarity between strings.</description>\n\t<url>http://www.ricecode.net</url>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<junit.version>4.13.1</junit.version>\n\t\t<mockito.version>1.10.19</mockito.version>\n\t</properties>\n\n\t<licenses>\n\t\t<license>\n\t\t\t<name>MIT License</name>\n\t\t\t<url>http://www.opensource.org/licenses/mit-license.php</url>\n\t\t\t<distribution>repo</distribution>\n\t\t</license>\n\t</licenses>\n\n\t<issueManagement>\n\t\t<url>https://github.com/rrice/java-string-similarity/issues</url>\n\t\t<system>GitHub Issues</system>\n\t</issueManagement>\n\n\t<scm>\n\t\t<url>https://github.com/rrice/java-string-similarity</url>\n\t\t<connection>scm:git:git://github.com/rrice/java-string-similarity.git</connection>\n\t\t<developerConnection>scm:git:git@github.com:rrice/java-string-similarity.git</developerConnection>\n\t  <tag>HEAD</tag>\n  </scm>\n\n\t<developers>\n\t\t<developer>\n\t\t\t<email>ralph.rice@gmail.com</email>\n\t\t\t<name>Ralph Allan Rice</name>\n\t\t\t<url>https://github.com/rrice</url>\n\t\t\t<id>rrice</id>\n\t\t</developer>\n\t</developers>\n\n\t<profiles>\n\t\t<profile>\n\t\t\t<id>doclint-java8-disable</id>\n\t\t\t<activation>\n\t\t\t\t<jdk>[1.8,)</jdk>\n\t\t\t</activation>\n\t\t\t<properties>\n\t\t\t\t<javadoc.opts>-Xdoclint:none</javadoc.opts>\n\t\t\t</properties>\n\t\t</profile>\n\t\t<profile>\n\t\t\t<id>release</id>\n\t\t\t<build>\n\t\t\t\t<plugins>\n\t\t\t\t\t<plugin>\n\t\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t\t<artifactId>maven-gpg-plugin</artifactId>\n\t\t\t\t\t\t<version>1.6</version>\n\t\t\t\t\t\t<executions>\n\t\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t\t<id>sign-artifacts</id>\n\t\t\t\t\t\t\t\t<phase>verify</phase>\n\t\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t\t<goal>sign</goal>\n\t\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t</execution>\n\t\t\t\t\t\t</executions>\n\t\t\t\t\t</plugin>\n\t\t\t\t</plugins>\n\t\t\t</build>\n\t\t</profile>\n\t</profiles>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.mockito</groupId>\n\t\t\t<artifactId>mockito-all</artifactId>\n\t\t\t<version>${mockito.version}</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>junit</groupId>\n\t\t\t<artifactId>junit</artifactId>\n\t\t\t<version>${junit.version}</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t<version>3.3</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<source>1.5</source>\n\t\t\t\t\t<target>1.5</target>\n\t\t\t\t\t<showwarnings>false</showwarnings>\n\t\t\t\t\t<showdeprecation>false</showdeprecation>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-source-plugin</artifactId>\n\t\t\t\t<version>2.4</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>attach-source</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>jar-no-fork</goal>\n\t\t\t\t\t\t\t<goal>test-jar-no-fork</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-javadoc-plugin</artifactId>\n\t\t\t\t<version>2.9.1</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<show>public</show>\n\t\t\t\t</configuration>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>attach-javadocs</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>jar</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<additionalparam>${javadoc.opts}</additionalparam>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-release-plugin</artifactId>\n\t\t\t\t<version>2.5.3</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<tagNameFormat>@{project.version}</tagNameFormat>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.sonatype.plugins</groupId>\n\t\t\t\t<artifactId>nexus-staging-maven-plugin</artifactId>\n\t\t\t\t<version>1.6.3</version>\n\t\t\t\t<extensions>true</extensions>\n\t\t\t\t<configuration>\n\t\t\t\t\t<serverId>ossrh</serverId>\n\t\t\t\t\t<nexusUrl>https://oss.sonatype.org/</nexusUrl>\n\t\t\t\t\t<autoReleaseAfterClose>true</autoReleaseAfterClose>\n\t\t\t\t</configuration>\n            </plugin>\n            <plugin>\n                <groupId>org.codehaus.mojo</groupId>\n                <artifactId>versions-maven-plugin</artifactId>\n                <version>2.2</version>\n            </plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "src/main/java/net/ricecode/similarity/AscendingSimilarityScoreComparator.java",
    "content": "/*\n * Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\npackage net.ricecode.similarity;\n\nimport java.util.Comparator;\n\n/**\n * A comparator that allows SimilarityScore to be sorted in\n * ascending order.\n * @author Ralph Allan Rice <ralph.rice@gmail.com>\n *\n */\npublic class AscendingSimilarityScoreComparator implements Comparator<SimilarityScore>\n{\n\t/**\n\t * Compares two similarity scores.\n\t * @param x The first score to be compared.\n\t * @param y The second score to be compared.\n\t * @return a negative integer, zero, or a positive integer as the first score is less than,\n\t * equal to, or greater than the second score. \n\t */\n\tpublic int compare(SimilarityScore x, SimilarityScore y) {\n\t\tdouble first = x.getScore();\n\t\tdouble second = y.getScore();\n\t\tif (first == second) {\n\t\t\treturn 0;\n\t\t}\n\t\tif (first < second) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn 1;\n\t}\n\t\n}\n"
  },
  {
    "path": "src/main/java/net/ricecode/similarity/DescendingSimilarityScoreComparator.java",
    "content": "/*\n * Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\npackage net.ricecode.similarity;\n\nimport java.util.Comparator;\n\n/**\n * A comparator that allows SimilarityScore to be sorted in\n * descending order.\n * @author Ralph Allan Rice <ralph.rice@gmail.com>\n *\n */\npublic class DescendingSimilarityScoreComparator implements Comparator<SimilarityScore>\n{\n\t/**\n\t * Compares two similarity scores.\n\t * @param x The first score to be compared.\n\t * @param y The second score to be compared.\n\t * @return a negative integer, zero, or a positive integer as the first score is greater than,\n\t * equal to, or less than the second score. \n\t */public int compare(SimilarityScore x, SimilarityScore y) {\n\t\tdouble first = x.getScore();\n\t\tdouble second = y.getScore();\n\t\tif (first == second) {\n\t\t\treturn 0;\n\t\t}\n\t\tif (first < second) {\n\t\t\treturn 1;\n\t\t}\n\t\treturn -1;\n\t}\n\t\n}\n\n"
  },
  {
    "path": "src/main/java/net/ricecode/similarity/DiceCoefficientStrategy.java",
    "content": "/*\n * Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\npackage net.ricecode.similarity;\n\nimport java.util.ArrayList;\nimport java.util.Set;\nimport java.util.TreeSet;\n\n/**\n * A strategy that uses the Dice's Coefficient to calculate the similarity of two strings.\n * @author Ralph Allan Rice <ralph.rice@gmail.com>\n * @see <a href=\"http://en.wikipedia.org/wiki/Dice%27s_coefficient\">About Dice Coefficient</a>\n */\npublic class DiceCoefficientStrategy implements SimilarityStrategy {\n\n\t/**\n\t * Calculates the similarity score of objects, where 0.0 implies absolutely no similarity\n\t * and 1.0 implies absolute similarity.\n\t * \n\t * @param first The first string to compare.\n\t * @param second The second string to compare.\n\t * @return A number between 0.0 and 1.0.\n\t */\n\tpublic double score(String first, String second) {\n\t\n\t\t// Create two sets of character bigrams, one for each string.\n\t\tSet<String> s1 = splitIntoBigrams(first);\n\t\tSet<String> s2 = splitIntoBigrams(second);\n\t\n\t\t// Get the number of elements in each set.\n\t\tint n1 = s1.size();\n\t\tint n2 = s2.size();\n\t\t\n\t\t// Find the intersection, and get the number of elements in that set.\n\t\ts1.retainAll(s2);\n\t\tint nt = s1.size();\n\t\t\n\t\t\n\t\t// The coefficient is:\n\t\t// \n\t\t//        2 ∙ | s1 ⋂ s2 |\n\t\t// D = ----------------------\n\t\t//        | s1 | + | s2 |\n\t\t// \n\t\treturn (2.0 * (double)nt) / ((double)(n1 + n2));\n\t\t\n\t}\n\n\t\n\tprivate Set<String> splitIntoBigrams(String s) {\n\t\tArrayList<String> bigrams = new ArrayList<String>();\n\t\n\t\tif (s.length() < 2) {\n\t\t\tbigrams.add(s);\n\t\t}\n\t\telse {\n\t\t\tfor (int i = 1; i < s.length(); i++) {\n\t\t\t\tStringBuilder sb = new StringBuilder();\n\t\t\t\tsb.append(s.charAt(i-1));\n\t\t\t\tsb.append(s.charAt(i));\n\t\t\t\tbigrams.add(sb.toString());\n\t\t\t}\n\t\t}\n\t\treturn new TreeSet<String>(bigrams);\n\t}\n\t\n\t\n\t\n}\n"
  },
  {
    "path": "src/main/java/net/ricecode/similarity/JaroStrategy.java",
    "content": "/*\n * Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\npackage net.ricecode.similarity;\n\n/**\n * A strategy that uses the Jaro Distance to calculate the similarity of two strings.\n * @author Ralph Allan Rice <ralph.rice@gmail.com>\n * @see <a href=\"http://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance\">About Jaro Distance</a>\n */\npublic class JaroStrategy implements SimilarityStrategy {\n\n\t/**\n\t * Calculates the similarity score of objects, where 0.0 implies absolutely no similarity\n\t * and 1.0 implies absolute similarity.\n\t * \n\t * @param first The first string to compare.\n\t * @param second The second string to compare.\n\t * @return A number between 0.0 and 1.0.\n\t */\n    public double score(String first, String second) {\n\t\tString shorter;\n        String longer;\n\n        // Determine which String is longer.\n        if (first.length() > second.length())\n        {\n            longer = first.toLowerCase();\n            shorter = second.toLowerCase();\n        }\n        else\n        {\n            longer = second.toLowerCase();\n            shorter = first.toLowerCase();\n        }\n\n        // Calculate the half length() distance of the shorter String.\n        int halflength = (shorter.length() / 2) + 1;\n\n        // Find the set of matching characters between the shorter and longer strings. Note that\n        // the set of matching characters may be different depending on the order of the strings.\n        String m1 = getSetOfMatchingCharacterWithin(shorter, longer, halflength);\n        String m2 = getSetOfMatchingCharacterWithin(longer, shorter, halflength);\n\n\n        // If one or both of the sets of common characters is empty, then \n        // there is no similarity between the two strings.\n        if (m1.length() == 0 || m2.length() == 0) return 0.0;\n\n        // If the set of common characters is not the same size, then\n        // there is no similarity between the two strings, either.\n        if (m1.length() != m2.length()) return 0.0;\n\n        // Calculate the number of transpositions between the two sets\n        // of common characters.\n        int transpositions = transpositions(m1, m2);\n\n        // Calculate the distance.\n        double dist =\n                (m1.length() / ((double)shorter.length()) +\n                m2.length() / ((double)longer.length()) +\n                (m1.length() - transpositions) / ((double)m1.length())) / 3.0;\n        return dist;\n\n\t\n\t}\n\t\n\t/**\n\t * Gets a set of matching characters between two strings.\n\t * \n\t * @param first The first string.\n\t * @param second The second string.\n\t * @param limit The maximum distance to consider.\n\t * @return A string contain the set of common characters.\n\t * @remarks Two characters from the first string and the second string are considered matching if the character's\n     * respective positions are no farther than the limit value.\n\t */\n\tprivate String getSetOfMatchingCharacterWithin(String first, String second, int limit)\n    {\n\n        StringBuilder common = new StringBuilder();\n        StringBuilder copy = new StringBuilder(second);\n        for (int i = 0; i < first.length(); i++)\n        {\n            char ch = first.charAt(i);\n            boolean found = false;\n\n            // See if the character is within the limit positions away from the original position of that character.\n            for (int j = Math.max(0, i - limit); !found && j < Math.min(i + limit, second.length()); j++)\n            {\n                if (copy.charAt(j) == ch)\n                {\n                    found = true;\n                    common.append(ch);\n                    copy.setCharAt(j,'*');\n                }\n            }\n        }\n        return common.toString();\n    }\n\n\t/**\n\t * Calculates the number of transpositions between two strings.\n\t * @param first The first string.\n\t * @param second The second string.\n\t * @return The number of transpositions between the two strings.\n\t */\n    private int transpositions(String first, String second)\n    {\n        int transpositions = 0;\n        for (int i = 0; i < first.length(); i++)\n        {\n            if (first.charAt(i) != second.charAt(i))\n            {\n                transpositions++;\n            }\n        }\n        transpositions /= 2;\n        return transpositions;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/net/ricecode/similarity/JaroWinklerStrategy.java",
    "content": "/*\n * Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\npackage net.ricecode.similarity;\n\n/**\n * A strategy that uses the Jaro-Winkler Distance to calculate the similarity of two strings.\n * \n * @author Ralph Allan Rice <ralph.rice@gmail.com>\n * @see <a href=\"http://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance\">About Jaro-Winkler Distance</a>\n */\npublic class JaroWinklerStrategy extends JaroStrategy implements SimilarityStrategy {\n\tfinal double DEFAULT_SCALING_FACTOR = 0.1;  // This is the default scaling factor Winkler used.\n\n    private double scalingFactor;\n    \n    /**\n     * Constructs a new JaroWinklerStrategy instance.\n     * @param scalingFactor The scaling factor between 0.00 and 0.25. If the scaling factor is greater than 0.25, the scaling factor is set to 0.25.\n     */\n    public JaroWinklerStrategy(double scalingFactor)\n    {\n        if (scalingFactor > 0.25)\n        {\n            scalingFactor = 0.25;    \n        }\n        this.scalingFactor = scalingFactor;\n    }\n\n    /**\n     * Constructs a new JaroWinklerStrategy instance.\n     */\n    public JaroWinklerStrategy()\n    {\n        this.scalingFactor = DEFAULT_SCALING_FACTOR;\n    }\n\n    /**\n\t * Calculates the similarity score of objects, where 0.0 implies absolutely no similarity\n\t * and 1.0 implies absolute similarity.\n\t * \n\t * @param first The first string to compare.\n\t * @param second The second string to compare.\n\t * @return A number between 0.0 and 1.0.\n\t */\n    public double score(String first, String second)\n    {\n        double jaro = super.score(first, second);\n\n        int cl = commonPrefixLength(first, second);\n\n        // The Jaro–Winkler distance uses a prefix scale which gives more favorable ratings\n        // to strings that match from the beginning for a set prefix length.\n        double winkler = jaro + (scalingFactor * cl * (1.0 - jaro));\n\n        return winkler;\n\n    }\n\n    /**\n     * Calculates the number of characters from the beginning of the strings that match exactly one-to-one, \n     * up to a maximum of four (4) characters.\n     * @param first The first string.\n     * @param second The second string.\n     * @return A number between 0 and 4.\n     */\n    private int commonPrefixLength(String first, String second)\n    {\n        String shorter;\n        String longer;\n\n        // Determine which string is longer.\n        if (first.length() > second.length())\n        {\n            longer = first.toLowerCase();\n            shorter = second.toLowerCase();\n        }\n        else\n        {\n            longer = second.toLowerCase();\n            shorter = first.toLowerCase();\n        }\n\n        int result = 0;\n\n        // Iterate through the shorter string.\n        for (int i = 0; i < shorter.length(); i++)\n        {\n            if (shorter.charAt(i) != longer.charAt(i))\n            {\n                break;\n            }\n            result++;\n        }\n\n        // Limit the result to 4.\n        return result > 4? 4: result;\n    }\n\n\t\n}\n"
  },
  {
    "path": "src/main/java/net/ricecode/similarity/LevenshteinDistanceStrategy.java",
    "content": "package net.ricecode.similarity;\n\n/**\n * A strategy that uses the Levenshtein's Distance to calculate the <i>edit distance</i> of two strings.\n * Then it converts this to a \"score\" to fit the framework.\n *\n * @see <a href=\"http://en.wikipedia.org/wiki/Levenshtein_distance\">About Levenshtein Distance</a>\n*/\npublic class LevenshteinDistanceStrategy implements SimilarityStrategy {\n    /**\n     * Calculates the similarity score of objects, where 0.0 implies absolutely no similarity\n     * and 1.0 implies absolute similarity.\n     *\n     * @param first The first string to compare.\n     * @param second The second string to compare.\n     * @return A number between 0.0 and 1.0.\n     * @throws NullPointerException if one or both of the strings are null\n     */\n    public double score(String first, String second) {\n        int maxLength = Math.max(first.length(), second.length());\n        //Can't divide by 0\n        if (maxLength == 0) return 1.0d;\n        return ((double) (maxLength - computeEditDistance(first, second))) / (double) maxLength;\n    }\n\n    protected int computeEditDistance(String first, String second) {\n        first = first.toLowerCase();\n        second = second.toLowerCase();\n\n        int[] costs = new int[second.length() + 1];\n        for (int i = 0; i <= first.length(); i++) {\n            int previousValue = i;\n            for (int j = 0; j <= second.length(); j++) {\n                if (i == 0) {\n                    costs[j] = j;\n                }\n                else if (j > 0) {\n                    int useValue = costs[j - 1];\n                    if (first.charAt(i - 1) != second.charAt(j - 1)) {\n                        useValue = Math.min(Math.min(useValue, previousValue), costs[j]) + 1;\n                    }\n                    costs[j - 1] = previousValue;\n                    previousValue = useValue;\n\n                }\n            }\n            if (i > 0) {\n                costs[second.length()] = previousValue;\n            }\n        }\n        return costs[second.length()];\n    }\n}\n"
  },
  {
    "path": "src/main/java/net/ricecode/similarity/SimilarityScore.java",
    "content": "/*\n * Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\npackage net.ricecode.similarity;\n\n/**\n * A value object contains a similarity score.\n * @author Ralph Allan Rice <ralph.rice@gmail.com>\n * \n */\npublic class SimilarityScore {\n\t\n\tprivate String key;\n\tprivate double score;\n\t\n\t/**\n\t * Constructs a similarity score.\n\t * @param key The string key.\n\t * @param score The score value.\n\t */\n\n\tpublic SimilarityScore(String key, double score) {\n\t\tthis.key = key;\n\t\tthis.score = score;\n\t}\n\t\n\t/**\n\t * Gets the key for this score.\n\t * @return A string.\n\t */\n\tpublic String getKey() {\n\t\treturn this.key;\n\t}\n\t\n\t/**\n\t * Gets the value of the score.\n\t * @return A double.\n\t */\n\tpublic double getScore() {\n\t\treturn this.score;\n\t}\n\n\t\n\t/**\n\t * Returns the hash code for this object.\n\t * @return An integer representing the hash code.\n\t */\n\tpublic int hashCode() {\n\t\tint hash = 11;\n\t\thash = 23 * hash + key.hashCode(); \n\t\thash = 23 * hash + (int)(score * 1000000);\n\t\treturn hash;\n\t}\n\t\n\t/**\n\t * Determines if the supplied object equals this object.\n\t * @return True if the keys and scores match between the two objects. Otherwise false.\n\t */\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif((o == null) || (o.getClass() != this.getClass())) {\n\t\t\treturn false; \n\t\t}\n\t\tSimilarityScore other=(SimilarityScore)o;\n\t\t\n\t\treturn this.key.equals(other.key)\n\t\t\t\t\t&& this.score == other.score;\n\t}\n\t\n\t\n}\n"
  },
  {
    "path": "src/main/java/net/ricecode/similarity/SimilarityStrategy.java",
    "content": "/*\n * Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\npackage net.ricecode.similarity;\n\n/**\n * @author Ralph Allan Rice <ralph.rice@gmail.com>\n * An interface that defines methods to perform string similarity calculation.\n */\npublic interface SimilarityStrategy {\n\n\t/**\n\t * Calculates the similarity score of objects, where 0.0 implies absolutely no similarity\n\t * and 1.0 implies absolute similarity.\n\t * \n\t * @param first The first string to compare.\n\t * @param second The second string to compare.\n\t * @return A number between 0.0 and 1.0.\n\t */\n    double score(String first, String second);\n}\n"
  },
  {
    "path": "src/main/java/net/ricecode/similarity/StringSimilarityService.java",
    "content": "/*\n * Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\npackage net.ricecode.similarity;\n\nimport java.util.Comparator;\nimport java.util.List;\n\n/**\n * A service that performs string similarity calculations.\n * @author Ralph Allan Rice <ralph.rice@gmail.com>\n *\n */\npublic interface StringSimilarityService {\n\n\t/**\n     * Calculates all similarity scores for a given set of features.\n     * @param features The list of features.\n     * @param target The target string to compare against the features.\n     * @return A list of similarity scores.\n     */\n    List<SimilarityScore> scoreAll(List<String> features, String target);\n\t\n    /**\n     * Calculates the similarity score of a single feature.\n     * @param feature The feature string to compare.\n     * @param target The target string to compare against the feature.\n     * @return The similarity score between the feature and target.\n     */\n    double score(String feature, String target);\n\n    \n    /**\n     * Finds the feature within a set of given features that best match the target string.\n     * @param features A list of strings containing the features to compare.\n     * @param target The target string to compare against the features.\n     * @return A SimilarityScore that has the highest score value amongst the features.\n     */\n    SimilarityScore findTop(List<String> features, String target);\n\n    /**\n     * Finds the feature within a set of given features that best match the target string.\n     * @param features A list of strings containing the features to compare.\n     * @param target The target string to compare against the features.\n     * @param comparator A comparator that is used sort the scores.  \n     * @return A SimilarityScore that has the top value amongst the features, according to the comparator.\n     */\n    SimilarityScore findTop(List<String> features, String target, Comparator<SimilarityScore> comparator);\n}\n"
  },
  {
    "path": "src/main/java/net/ricecode/similarity/StringSimilarityServiceImpl.java",
    "content": "/*\n * Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\npackage net.ricecode.similarity;\n\nimport java.util.ArrayList;\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.Collections;\n\n\n/**\n * An implementation of StringSimilarityService.\n * @author Ralph Allan Rice <ralph.rice@gmail.com>\n * @see StringSimilarityService\n */\npublic class StringSimilarityServiceImpl implements StringSimilarityService {\n\n\tprivate SimilarityStrategy strategy;\n\n\n    /**\n     * Creates a similarity calculator instance.\n     * @param strategy The similarity strategy to use when calculating similarity scores.\n     */\n    public StringSimilarityServiceImpl(SimilarityStrategy strategy) {\n        this.strategy = strategy;\n    }\n\n    /**\n     * Calculates all similarity scores for a given set of features.\n     * @param features The list of features.\n     * @param target The target string to compare against the features.\n     * @return A list of similarity scores.\n     */\n    public List<SimilarityScore> scoreAll(List<String> features, String target)\n    {\n        ArrayList<SimilarityScore> scores = new ArrayList<SimilarityScore>();\n        \n        for(String feature: features) {\n        \tdouble score = strategy.score(feature, target);\n        \tscores.add(new SimilarityScore(feature, score));\n        }\n        \n        return scores;\n    }\n\n\n    /**\n     * Calculates the similarity score of a single feature.\n     * @param feature The feature string to compare.\n     * @param target The target string to compare against the feature.\n     * @return The similarity score between the feature and target.\n     */\n    public double score(String feature, String target)\n    {\n        return strategy.score(feature, target);\n    }\n\n    /**\n     * Finds the feature within a set of given features that best match the target string.\n     * @param features A list of strings containing the features to compare.\n     * @param target The target string to compare against the features.\n     * @return The similarity score with the highest value.\n     */\n    public SimilarityScore findTop(List<String> features, String target)\n    {\n    \treturn findTop(features, target, new DescendingSimilarityScoreComparator());\n    }\n    \n    /**\n     * Finds the feature within a set of given features that best match the target string.\n     * @param features A list of strings containing the features to compare.\n     * @param target The target string to compare against the features.\n     * @param comparator A comparator that is used sort the scores.  \n     * @return A SimilarityScore that has the top value amongst the features, according to the comparator.\n     */\n    public SimilarityScore findTop(List<String> features, String target, Comparator<SimilarityScore> comparator)\n    {\n    \tif (features.size() == 0) {\n    \t\treturn null;\n    \t}\n    \tList<SimilarityScore> scores= scoreAll(features, target);\n    \tCollections.sort(scores, comparator);\n    \treturn scores.get(0);\n    }\n}\n"
  },
  {
    "path": "src/test/java/net/ricecode/similarity/AscendingComparatorTest.java",
    "content": "/*\n * Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\npackage net.ricecode.similarity;\n\nimport static org.junit.Assert.*;\n\nimport org.junit.Test;\n\npublic class AscendingComparatorTest {\n\n\t@Test\n\tpublic void testCompareScoreFirstGreater() {\n\t\tSimilarityScore first = new SimilarityScore(\"First\", 0.87);\n\t\tSimilarityScore second = new SimilarityScore(\"Second\", 0.54);\n\t\tAscendingSimilarityScoreComparator c = new AscendingSimilarityScoreComparator();\n\t\tassertTrue(c.compare(first, second)>0);\n\t\tassertTrue(c.compare(second, first)<0);\n\t}\n\t\n\t@Test\n\tpublic void testCompareScoreSecondGreater() {\n\t\tSimilarityScore first = new SimilarityScore(\"First\", 0.37);\n\t\tSimilarityScore second = new SimilarityScore(\"Second\", 0.65);\n\t\tAscendingSimilarityScoreComparator c = new AscendingSimilarityScoreComparator();\n\t\tassertTrue(c.compare(first, second)<0);\n\t\tassertTrue(c.compare(second, first)>0);\n\t}\n\n\t@Test\n\tpublic void testCompareScoreEquality() {\n\t\tSimilarityScore first = new SimilarityScore(\"First\", 0.96);\n\t\tSimilarityScore second = new SimilarityScore(\"Second\", 0.96);\n\t\tAscendingSimilarityScoreComparator c = new AscendingSimilarityScoreComparator();\n\t\tassertEquals(c.compare(first, second), 0);\n\t\tassertEquals(c.compare(second, first), 0);\n\t}\n\n}\n"
  },
  {
    "path": "src/test/java/net/ricecode/similarity/DescendingComparatorTest.java",
    "content": "/*\n * Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\npackage net.ricecode.similarity;\n\nimport static org.junit.Assert.*;\n\nimport org.junit.Test;\n\npublic class DescendingComparatorTest {\n\n\t@Test\n\tpublic void testCompareScoreFirstGreater() {\n\t\tSimilarityScore first = new SimilarityScore(\"First\", 0.87);\n\t\tSimilarityScore second = new SimilarityScore(\"Second\", 0.54);\n\t\tDescendingSimilarityScoreComparator c = new DescendingSimilarityScoreComparator();\n\t\tassertTrue(c.compare(first, second)<0);\n\t\tassertTrue(c.compare(second, first)>0);\n\t}\n\t\n\t@Test\n\tpublic void testCompareScoreSecondGreater() {\n\t\tSimilarityScore first = new SimilarityScore(\"First\", 0.37);\n\t\tSimilarityScore second = new SimilarityScore(\"Second\", 0.65);\n\t\tDescendingSimilarityScoreComparator c = new DescendingSimilarityScoreComparator();\n\t\tassertTrue(c.compare(first, second)>0);\n\t\tassertTrue(c.compare(second, first)<0);\n\t}\n\n\t@Test\n\tpublic void testCompareScoreEquality() {\n\t\tSimilarityScore first = new SimilarityScore(\"First\", 0.96);\n\t\tSimilarityScore second = new SimilarityScore(\"Second\", 0.96);\n\t\tDescendingSimilarityScoreComparator c = new DescendingSimilarityScoreComparator();\n\t\tassertEquals(c.compare(first, second), 0);\n\t\tassertEquals(c.compare(second, first), 0);\n\t}\n\n}\n"
  },
  {
    "path": "src/test/java/net/ricecode/similarity/DiceCoefficientStrategyTest.java",
    "content": "/*\n * Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\npackage net.ricecode.similarity;\n\nimport static org.junit.Assert.*;\n\nimport org.junit.Test;\n\npublic class DiceCoefficientStrategyTest {\n\n\t@Test\n\tpublic void testOneTranspostion() {\n\t\tSimilarityStrategy s = new DiceCoefficientStrategy();\n\t\tString first = \"Martha\";\n\t\tString second = \"Marhta\";\n\t\tdouble expected = 0.400;\n\t\tdouble delta = 0.001;\n\t\tdouble actual = s.score(first, second);\n\t\tassertEquals(expected, actual, delta);\n\t}\n\n\t@Test\n\tpublic void testSoundAlike() {\n\t\tSimilarityStrategy s = new DiceCoefficientStrategy();\n\t\tString first = \"Dwayne\";\n\t\tString second = \"Duane\";\n\t\tdouble expected = 0.2222;\n\t\tdouble delta = 0.001;\n\t\tdouble actual = s.score(first, second);\n\t\tassertEquals(expected, actual, delta);\n\t\t\n\t}\n\t\n\t@Test\n\tpublic void testMisspelledSoundAlike() {\n\t\tSimilarityStrategy s = new DiceCoefficientStrategy();\n\t\tString first = \"Dixon\";\n\t\tString second = \"Dicksonx\";\n\t\tdouble expected = 0.363636;\n\t\tdouble delta = 0.001;\n\t\tdouble actual = s.score(first, second);\n\t\tassertEquals(expected, actual, delta);\n\t\t\n\t}\n\t\n\t@Test\n\tpublic void testAbsoluteSimilarity() {\n\t\tSimilarityStrategy s = new DiceCoefficientStrategy();\n\t\tString first = \"Mississippi\";\n\t\tString second = \"Mississippi\";\n\t\tdouble expected = 1.000;\n\t\tdouble delta = 0.000;\n\t\tdouble actual = s.score(first, second);\n\t\tassertEquals(expected, actual, delta);\n\t}\n\t\n\t@Test\n\tpublic void testAbsoluteDissimilarity() {\n\t\tSimilarityStrategy s = new DiceCoefficientStrategy();\n\t\tString first = \"Mississippi\";\n\t\tString second = \"Oklahoma\";\n\t\tdouble expected = 0.000;\n\t\tdouble delta = 0.000;\n\t\tdouble actual = s.score(first, second);\n\t\tassertEquals(expected, actual, delta);\n\t}\n\n}\n"
  },
  {
    "path": "src/test/java/net/ricecode/similarity/JaroStrategyTest.java",
    "content": "/*\n * Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\npackage net.ricecode.similarity;\n\nimport static org.junit.Assert.*;\nimport org.junit.Test;\n\npublic class JaroStrategyTest {\n\n\t@Test\n\tpublic void testOneTranspostion() {\n\t\tSimilarityStrategy s = new JaroStrategy();\n\t\tString first = \"Martha\";\n\t\tString second = \"Marhta\";\n\t\tdouble expected = 0.944;\n\t\tdouble delta = 0.001;\n\t\tdouble actual = s.score(first, second);\n\t\tassertEquals(expected, actual, delta);\n\t}\n\n\t@Test\n\tpublic void testSoundAlike() {\n\t\tSimilarityStrategy s = new JaroStrategy();\n\t\tString first = \"Dwayne\";\n\t\tString second = \"Duane\";\n\t\tdouble expected = 0.822;\n\t\tdouble delta = 0.001;\n\t\tdouble actual = s.score(first, second);\n\t\tassertEquals(expected, actual, delta);\n\t\t\n\t}\n\t\n\t@Test\n\tpublic void testMisspelledSoundAlike() {\n\t\tSimilarityStrategy s = new JaroStrategy();\n\t\tString first = \"Dixon\";\n\t\tString second = \"Dicksonx\";\n\t\tdouble expected = 0.767;\n\t\tdouble delta = 0.001;\n\t\tdouble actual = s.score(first, second);\n\t\tassertEquals(expected, actual, delta);\n\t\t\n\t}\n\t\n\t@Test\n\tpublic void testAbsoluteSimilarity() {\n\t\tSimilarityStrategy s = new JaroStrategy();\n\t\tString first = \"Mississippi\";\n\t\tString second = \"Mississippi\";\n\t\tdouble expected = 1.000;\n\t\tdouble delta = 0.000;\n\t\tdouble actual = s.score(first, second);\n\t\tassertEquals(expected, actual, delta);\n\t}\n\t\n\t@Test\n\tpublic void testAbsoluteDissimilarity() {\n\t\tSimilarityStrategy s = new JaroStrategy();\n\t\tString first = \"Mississippi\";\n\t\tString second = \"Oklahoma\";\n\t\tdouble expected = 0.000;\n\t\tdouble delta = 0.000;\n\t\tdouble actual = s.score(first, second);\n\t\tassertEquals(expected, actual, delta);\n\t}\n\t\n}\n"
  },
  {
    "path": "src/test/java/net/ricecode/similarity/JaroWinklerStrategyTest.java",
    "content": "/*\n * Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\npackage net.ricecode.similarity;\n\nimport static org.junit.Assert.*;\n\nimport org.junit.Test;\n\npublic class JaroWinklerStrategyTest {\n\n\t@Test\n\tpublic void testOneTranspostion() {\n\t\tSimilarityStrategy s = new JaroWinklerStrategy();\n\t\tString first = \"Martha\";\n\t\tString second = \"Marhta\";\n\t\tdouble expected = 0.961;\n\t\tdouble delta = 0.001;\n\t\tdouble actual = s.score(first, second);\n\t\tassertEquals(expected, actual, delta);\n\t}\n\n\t@Test\n\tpublic void testSoundAlike() {\n\t\tSimilarityStrategy s = new JaroWinklerStrategy();\n\t\tString first = \"Dwayne\";\n\t\tString second = \"Duane\";\n\t\tdouble expected = 0.840;\n\t\tdouble delta = 0.001;\n\t\tdouble actual = s.score(first, second);\n\t\tassertEquals(expected, actual, delta);\n\t\t\n\t}\n\t\n\t@Test\n\tpublic void testMisspelledSoundAlike() {\n\t\tSimilarityStrategy s = new JaroWinklerStrategy();\n\t\tString first = \"Dixon\";\n\t\tString second = \"Dicksonx\";\n\t\tdouble expected = 0.813;\n\t\tdouble delta = 0.001;\n\t\tdouble actual = s.score(first, second);\n\t\tassertEquals(expected, actual, delta);\n\t\t\n\t}\n\t\n\t@Test\n\tpublic void testAbsoluteSimilarity() {\n\t\tSimilarityStrategy s = new JaroStrategy();\n\t\tString first = \"Mississippi\";\n\t\tString second = \"Mississippi\";\n\t\tdouble expected = 1.000;\n\t\tdouble delta = 0.000;\n\t\tdouble actual = s.score(first, second);\n\t\tassertEquals(expected, actual, delta);\n\t}\n\t\n\t@Test\n\tpublic void testAbsoluteDissimilarity() {\n\t\tSimilarityStrategy s = new JaroStrategy();\n\t\tString first = \"Mississippi\";\n\t\tString second = \"Oklahoma\";\n\t\tdouble expected = 0.000;\n\t\tdouble delta = 0.000;\n\t\tdouble actual = s.score(first, second);\n\t\tassertEquals(expected, actual, delta);\n\t}\n}"
  },
  {
    "path": "src/test/java/net/ricecode/similarity/LevenshteinDistanceStrategyTest.java",
    "content": "package net.ricecode.similarity;\n\nimport org.junit.Test;\nimport static org.junit.Assert.*;\n\npublic class LevenshteinDistanceStrategyTest {\n\n    @Test (expected = NullPointerException.class)\n    public void testNullThrows() {\n        LevenshteinDistanceStrategy lds = new LevenshteinDistanceStrategy();\n        lds.score(null, \"kEvIn\");\n    }\n\n    @Test\n    public void emptyStringTest() {\n        LevenshteinDistanceStrategy lds = new LevenshteinDistanceStrategy();\n        double response = lds.score(\"\", \"\");\n        assertEquals(1.0, response, 0.0);\n    }\n\n    @Test\n    public void testExactMatchDifferentCase() {\n        LevenshteinDistanceStrategy lds = new LevenshteinDistanceStrategy();\n        double response = lds.score(\"KeViN\", \"kevin\");\n        assertEquals(1.0, response, 0.0);\n    }\n\n    @Test\n    public void testExactMatchSameCase() {\n        LevenshteinDistanceStrategy lds = new LevenshteinDistanceStrategy();\n        double response = lds.score(\"java\", \"java\");\n        assertEquals(1.0, response, 0.0);\n    }\n\n    @Test\n    public void testNoSimilarity() {\n        LevenshteinDistanceStrategy lds = new LevenshteinDistanceStrategy();\n        double response = lds.score(\"abc\", \"def\");\n        assertEquals(0.0, response, 0.0);\n    }\n\n    @Test\n    public void score1() {\n        LevenshteinDistanceStrategy lds = new LevenshteinDistanceStrategy();\n        double response = lds.score(\"he\", \"head\");\n        assertEquals(0.5d, response, 0.0001d);\n    }\n\n    @Test\n    public void score2() {\n        LevenshteinDistanceStrategy lds = new LevenshteinDistanceStrategy();\n        double response = lds.score(\"hd\", \"head\");\n        assertEquals(0.5d, response, 0.0001d);\n    }\n\n    @Test\n    public void score3() {\n        LevenshteinDistanceStrategy lds = new LevenshteinDistanceStrategy();\n        double response = lds.score(\"d\", \"head\");\n        assertEquals(0.25d, response, 0.0001d);\n    }\n\n    @Test\n    public void score4() {\n        LevenshteinDistanceStrategy lds = new LevenshteinDistanceStrategy();\n        double response = lds.score(\"head\", \"he\");\n        assertEquals(0.5d, response, 0.0001d);\n    }\n\n    @Test\n    public void score5() {\n        LevenshteinDistanceStrategy lds = new LevenshteinDistanceStrategy();\n        double response = lds.score(\"kitten\", \"sitting\");\n        assertEquals(0.5714d, response, 0.0001d);\n    }\n\n    @Test\n    public void score6() {\n        LevenshteinDistanceStrategy lds = new LevenshteinDistanceStrategy();\n        double response = lds.score(\"Saturday\", \"Sunday\");\n        assertEquals(0.625d, response, 0.0001d);\n    }\n\n\n\n\n}\n"
  },
  {
    "path": "src/test/java/net/ricecode/similarity/SimilarityScoreTest.java",
    "content": "/*\n * Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\npackage net.ricecode.similarity;\n\nimport static org.junit.Assert.*;\n\nimport org.junit.Test;\n\npublic class SimilarityScoreTest {\n\n\t@Test\n\tpublic void testGetKey() {\n\t\tSimilarityScore s = new SimilarityScore(\"Test\", 0.99);\n\t\tassertEquals(\"Test\", s.getKey());\n\t}\n\n\t@Test\n\tpublic void testGetScore() {\n\t\tSimilarityScore s = new SimilarityScore(\"Test\", 0.99);\n\t\tassertEquals(0.99, s.getScore(), 0.000);\n\t\t\n\t}\n\n\t\n\t\n}\n"
  },
  {
    "path": "src/test/java/net/ricecode/similarity/StringSimilarityServiceImplTest.java",
    "content": "/*\n * Copyright (c) 2010 Ralph Allan Rice <ralph.rice@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\npackage net.ricecode.similarity;\n\nimport static org.junit.Assert.*;\nimport static org.mockito.Mockito.*;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.junit.Test;\n\n\npublic class StringSimilarityServiceImplTest {\n\n\t\n\t@Test\n\tpublic void testScoreAll() {\n\t\tSimilarityStrategy strategy = mock(SimilarityStrategy.class);\n\t\tString target = \"McDonalds\";\n\t\tString c1 = \"MacMahons\";\n\t\tString c2 = \"McPherson\";\n\t\tString c3 = \"McDonalds\";\n\t\t\n\t\twhen(strategy.score(target, c1)).thenReturn(0.90);\n\t\twhen(strategy.score(target, c2)).thenReturn(0.74);\n\t\twhen(strategy.score(target, c3)).thenReturn(1.000);\n\t\t\n\t\tStringSimilarityService service = new StringSimilarityServiceImpl(strategy);\n\t\tList<String> features = new ArrayList<String>();\n\t\tfeatures.add(c1);\n\t\tfeatures.add(c2);\n\t\tfeatures.add(c3);\n\t\t\n\t\tList<SimilarityScore> scores = service.scoreAll(features, target);\n\t\tverify(strategy).score(c1, target);\n\t\tverify(strategy).score(c2, target);\n\t\tverify(strategy).score(c3, target);\n\t\tassertEquals(3, scores.size());\n\t}\n\n\t@Test\n\tpublic void testScore() {\n\t\tSimilarityStrategy strategy = mock(SimilarityStrategy.class);\n\t\tString target = \"McDonalds\";\n\t\tString c1 = \"MacMahons\";\n\t\tString c2 = \"McPherson\";\n\t\tString c3 = \"McDonalds\";\n\t\t\n\t\twhen(strategy.score(c1, target)).thenReturn(0.90);\n\t\twhen(strategy.score(c2, target)).thenReturn(0.74);\n\t\twhen(strategy.score(c3, target)).thenReturn(1.000);\n\t\t\n\t\tStringSimilarityService service = new StringSimilarityServiceImpl(strategy);\n\t\t\n\t\tdouble score = service.score(c1, target);\n\t\tverify(strategy).score(c1, target);\n\t\tassertEquals(0.90, score, 0.000);\n\t\t\n\t}\n\n\t@Test \n\tpublic void testFindTop() {\n\t\tSimilarityStrategy strategy = mock(SimilarityStrategy.class);\n\t\tString target = \"McDonalds\";\n\t\tString c1 = \"MacMahons\";\n\t\tString c2 = \"McPherson\";\n\t\tString c3 = \"McDonalds\";\n\t\t\n\t\tSimilarityScore expected = new SimilarityScore(c3, 1.000);\n\t\t\n\t\twhen(strategy.score(c1, target)).thenReturn(0.90);\n\t\twhen(strategy.score(c2, target)).thenReturn(0.74);\n\t\twhen(strategy.score(c3, target)).thenReturn(1.000);\n\t\t\n\t\tStringSimilarityService service = new StringSimilarityServiceImpl(strategy);\n\t\tList<String> features = new ArrayList<String>();\n\t\tfeatures.add(c1);\n\t\tfeatures.add(c2);\n\t\tfeatures.add(c3);\n\t\t\n\t\tSimilarityScore top= service.findTop(features,target);\n\t\tverify(strategy).score(c1, target);\n\t\tverify(strategy).score(c2, target);\n\t\tverify(strategy).score(c3, target);\n\t\tassertEquals(expected, top);\n\t\t\n\t}\n\t\n\t@Test \n\tpublic void testFindTop_Ascending() {\n\t\tSimilarityStrategy strategy = mock(SimilarityStrategy.class);\n\t\tString target = \"McDonalds\";\n\t\tString c1 = \"MacMahons\";\n\t\tString c2 = \"McPherson\";\n\t\tString c3 = \"McDonalds\";\n\t\t\n\t\tSimilarityScore expected = new SimilarityScore(c2, 0.74);\n\t\t\n\t\twhen(strategy.score(c1, target)).thenReturn(0.90);\n\t\twhen(strategy.score(c2, target)).thenReturn(0.74);\n\t\twhen(strategy.score(c3, target)).thenReturn(1.000);\n\t\t\n\t\tStringSimilarityService service = new StringSimilarityServiceImpl(strategy);\n\t\tList<String> features = new ArrayList<String>();\n\t\tfeatures.add(c1);\n\t\tfeatures.add(c2);\n\t\tfeatures.add(c3);\n\t\t\n\t\tAscendingSimilarityScoreComparator comparator = new AscendingSimilarityScoreComparator();\n\t\tSimilarityScore top= service.findTop(features,target, comparator);\n\t\tverify(strategy).score(c1, target);\n\t\tverify(strategy).score(c2, target);\n\t\tverify(strategy).score(c3, target);\n\t\tassertEquals(expected, top);\n\t}\n\t\n\t@Test \n\tpublic void testFindTop_Descending() {\n\t\tSimilarityStrategy strategy = mock(SimilarityStrategy.class);\n\t\tString target = \"McDonalds\";\n\t\tString c1 = \"MacMahons\";\n\t\tString c2 = \"McPherson\";\n\t\tString c3 = \"McDonalds\";\n\t\t\n\t\tSimilarityScore expected = new SimilarityScore(c3, 1.000);\n\t\t\n\t\twhen(strategy.score(c1, target)).thenReturn(0.90);\n\t\twhen(strategy.score(c2, target)).thenReturn(0.74);\n\t\twhen(strategy.score(c3, target)).thenReturn(1.000);\n\t\t\n\t\tStringSimilarityService service = new StringSimilarityServiceImpl(strategy);\n\t\tList<String> features = new ArrayList<String>();\n\t\tfeatures.add(c1);\n\t\tfeatures.add(c2);\n\t\tfeatures.add(c3);\n\t\t\n\t\tDescendingSimilarityScoreComparator comparator = new DescendingSimilarityScoreComparator();\n\t\tSimilarityScore top= service.findTop(features,target, comparator);\n\t\tverify(strategy).score(c1, target);\n\t\tverify(strategy).score(c2, target);\n\t\tverify(strategy).score(c3, target);\n\t\tassertEquals(expected, top);\n\t\t\n\t}\n}\n"
  }
]