Библиотека Java для свободной текстовой разности [закрылась]

Чтобы включить тот же edmx для доступа к нескольким базам данных и поставщикам баз данных, и наоборот, я использую следующий метод:

1) Определить ConnectionManager:

public static class ConnectionManager
{
    public static string GetConnectionString(string modelName)
    {
        var resourceAssembly = Assembly.GetCallingAssembly();

        var resources = resourceAssembly.GetManifestResourceNames();

        if (!resources.Contains(modelName + ".csdl")
            || !resources.Contains(modelName + ".ssdl")
            || !resources.Contains(modelName + ".msl"))
        {
            throw new ApplicationException(
                    "Could not find connection resources required by assembly: "
                    + System.Reflection.Assembly.GetCallingAssembly().FullName);
        }

        var provider = System.Configuration.ConfigurationManager.AppSettings.Get(
                        "MyModelUnitOfWorkProvider");

        var providerConnectionString = System.Configuration.ConfigurationManager.AppSettings.Get(
                        "MyModelUnitOfWorkConnectionString");

        string ssdlText;

        using (var ssdlInput = resourceAssembly.GetManifestResourceStream(modelName + ".ssdl"))
        {
            using (var textReader = new StreamReader(ssdlInput))
            {
                ssdlText = textReader.ReadToEnd();
            }
        }

        var token = "Provider=\"";
        var start = ssdlText.IndexOf(token);
        var end = ssdlText.IndexOf('"', start + token.Length);
        var oldProvider = ssdlText.Substring(start, end + 1 - start);

        ssdlText = ssdlText.Replace(oldProvider, "Provider=\"" + provider + "\"");

        var tempDir = Environment.GetEnvironmentVariable("TEMP") + '\\' + resourceAssembly.GetName().Name;
        Directory.CreateDirectory(tempDir);

        var ssdlOutputPath = tempDir + '\\' + Guid.NewGuid() + ".ssdl";

        using (var outputFile = new FileStream(ssdlOutputPath, FileMode.Create))
        {
            using (var outputStream = new StreamWriter(outputFile))
            {
                outputStream.Write(ssdlText);
            }
        }

        var eBuilder = new EntityConnectionStringBuilder
        {
            Provider = provider,

            Metadata = "res://*/" + modelName + ".csdl"
                        + "|" + ssdlOutputPath
                        + "|res://*/" + modelName + ".msl",

            ProviderConnectionString = providerConnectionString
        };

        return eBuilder.ToString();
    }
}

2) Изменить T4, который создает ваш ObjectContext, чтобы он использовал ConnectionManager:

public partial class MyModelUnitOfWork : ObjectContext
{
    public const string ContainerName = "MyModelUnitOfWork";
    public static readonly string ConnectionString
        = ConnectionManager.GetConnectionString("MyModel");

3) Добавьте следующие строки в App.Config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
    <add name="MyModelUnitOfWork" connectionString=... />
  </connectionStrings>
  <appSettings>
    <add key="MyModelUnitOfWorkConnectionString" value="data source=MyPc\SqlExpress;initial catalog=MyDB;integrated security=True;multipleactiveresultsets=True" />
    <add key="MyModelUnitOfWorkProvider" value="System.Data.SqlClient" />
  </appSettings>
</configuration>

ConnectionManager заменит ConnectionString и Provider к тому, что когда-либо было в App.Config.

Вы можете использовать тот же ConnectionManager для всех объектов ObjectContext (чтобы все они читали одни и те же настройки из App.Config) или редактировали T4, чтобы он создавал один ConnectionManager для каждого (в собственном пространстве имен), так что каждый считывает отдельные настройки.

17
задан Joshua Fox 26 January 2009 в 15:35
поделиться

4 ответа

Этот мог бы быть хорош Различный Патч Соответствия .

16
ответ дан 30 November 2019 в 13:13
поделиться

В зависимости от Ваших строгих требований StringUtils класс компонент Apache Commons Lang мог бы быть полезным, например:

  • StringUtils#difference: Сравнивает две Строки и возвращает часть, где они отличаются
  • StringUtils#getLevenshteinDistance: Найдите расстояние Левенштейна между двумя Строками
8
ответ дан 30 November 2019 в 13:13
поделиться

Вот (слегка протестированная) версия кода, который делает то, что Вы спросили. Можно легко пересечь результат параллельно с исходными данными для определения местоположения вставок и удалений.

public class StringDiff {

    private static int   length(String s) { return s == null ? 0 : s.length(); }
    private static char[] chars(String s) { return s == null ? new char[0] : s.toCharArray(); }

    private final String left;
    private final String right;

    private final char[] lccs;
    private final String lcs;

    public StringDiff(String left, String right) {
        this.left = left;
        this.right = right;
        lccs = init();
        lcs = new String(lccs);
    }

    public String getLcs()  { return lcs; }
    public char[] getLccs() { return lccs.clone(); }

    private char[] init() {
        int lLength = length(left);
        int rLength = length(right);
        char[] lChars = chars(left);
        char[] rChars = chars(right);
        int [][] t = new int [lLength + 1][rLength + 1];
        for (int i = lLength - 1; i >= 0; --i) {
            for (int j = rLength - 1; j >= 0; --j) {
                if (lChars[i] == rChars[j]) {
                    t[i][j] = t[i + 1][j + 1] + 1;
                } else {
                    t[i][j] = Math.max(t[i + 1][j], t[i][j + 1]);
                }
            }
        }
        char[] result = new char[t[0][0]];
        int l = 0, r = 0, p = 0;
        while (l < lLength && r < rLength) {
            if (lChars[l] == rChars[r]) {
                result[p++] = lChars[l++];
                r++;
            } else {
                if (t[l + 1][r] > t[l][r + 1]) {
                    ++l;
                } else {
                    ++r;
                }
            }
        }
        return result;
    }

}

Согласно ему, фактическая самая длинная подпоследовательность Ваших исходных исходных данных:

The quick brown  fox jumped over the  lazy     dog.
The quick yellow fox jumped over the well-bred dog.

:

The quick ow fox jumped over the l dog.

(потому что "коричневый" и "желтый" имеют "ой" вместе, и т.д.)

Это относительно просто для изменения вышеупомянутого, чтобы разделить на пробеле (вместо в массивы символов) и заменить String#equals == для получения версии, которая находит самую длинную общую подпоследовательность слов вместо символов. Поскольку Ваш пример выше того изменения привел бы к очевидному результату:

found 7 words
    'The'
    'quick'
    'fox'
    'jumped'
    'over'
    'the'
    'dog.'

(Ваш вопрос подразумеваемые символьные сравнения, когда Вы соответствовали пробелам между словами.)

1
ответ дан 30 November 2019 в 13:13
поделиться

Если Вы - пример, действительно, что Вы хотите сделать - т.е. подпоследовательности только соответствуют, если они запускают в том же индексе (который отличается от того, как diffs обычно работают) - это - все, что необходимо сделать:

import java.util.*;

class StringDiff {
    public static List<int[]> from(String s1, String s2) {
        int start = -1;
        int pos = 0;
        LinkedList<int[]> list = new LinkedList<int[]>();

        for(; pos < s1.length() && pos < s2.length(); ++pos) {
            if(s1.charAt(pos) == s2.charAt(pos)) {
                if(start < 0) start = pos;
            }
            else {
                if(start >= 0) list.add(new int[] { start, pos });
                start = -1;
            }
        }

        if(start >= 0) list.add(new int[] { start, pos });

        return list;
    }

    public static void main(String[] args) {
        for(int[] idx : from(args[0], args[1]))
            System.out.println(args[0].substring(idx[0], idx[1]));
    }
}

фактическая различная реализация будет намного более сложной.

0
ответ дан 30 November 2019 в 13:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: