public Object[] patch_apply(LinkedList<Patch> patches, String text) {
        if (patches.isEmpty()) {
            return new Object[] { text, new boolean[0] };
        }

        // Deep copy the patches so that no changes are made to originals.
        patches = patch_deepCopy(patches);

        String nullPadding = patch_addPadding(patches);
        text = nullPadding + text + nullPadding;
        patch_splitMax(patches);

        int x = 0;
        // delta keeps track of the offset between the expected and actual
        // location
        // of the previous patch. If there are patches expected at positions 10
        // and
        // 20, but the first patch was found at 12, delta is 2 and the second
        // patch
        // has an effective expected position of 22.
        int delta = 0;
        boolean[] results = new boolean[patches.size()];
        for (Patch aPatch : patches) {
            int expected_loc = aPatch.start2 + delta;
            String text1 = diff_text1(aPatch.diffs);
            int start_loc;
            int end_loc = -1;
            if (text1.length() > Match_MaxBits) {
                // patch_splitMax will only provide an oversized pattern in the
                // case of
                // a monster delete.
                start_loc = match_main(text,
                        text1.substring(0, Match_MaxBits), expected_loc);
                if (start_loc != -1) {
                    end_loc = match_main(text, text1.substring(text1.length()
                            - Match_MaxBits),
                            expected_loc + text1.length() - Match_MaxBits);
                    if (end_loc == -1 || start_loc >= end_loc) {
                        // Can't find valid trailing context. Drop this patch.
                        start_loc = -1;
                    }
                }
            } else {
                start_loc = match_main(text, text1, expected_loc);
            }
            if (start_loc == -1) {
                // No match found. :(
                results[x] = false;
                // Subtract the delta for this failed patch from subsequent
                // patches.
                delta -= aPatch.length2 - aPatch.length1;
            } else {
                // Found a match. :)
                results[x] = true;
                delta = start_loc - expected_loc;
                String text2;
                if (end_loc == -1) {
                    text2 = text
                            .substring(
                                    start_loc,
                                    Math.min(start_loc + text1.length(),
                                            text.length()));
                } else {
                    text2 = text.substring(start_loc,
                            Math.min(end_loc + Match_MaxBits, text.length()));
                }
                if (text1.equals(text2)) {
                    // Perfect match, just shove the replacement text in.
                    text = text.substring(0, start_loc)
                            + diff_text2(aPatch.diffs)
                            + text.substring(start_loc + text1.length());
                } else {
                    // Imperfect match. Run a diff to get a framework of
                    // equivalent
                    // indices.
                    LinkedList<Diff> diffs = diff_main(text1, text2, false);
                    if (text1.length() > Match_MaxBits
                            && diff_levenshtein(diffs) / (float) text1.length() > Patch_DeleteThreshold) {
                        // The end points match, but the content is unacceptably
                        // bad.
                        results[x] = false;
                    } else {
                        diff_cleanupSemanticLossless(diffs);
                        int index1 = 0;
                        for (Diff aDiff : aPatch.diffs) {
                            if (aDiff.operation != Operation.EQUAL) {
                                int index2 = diff_xIndex(diffs, index1);
                                if (aDiff.operation == Operation.INSERT) {
                                    // Insertion
                                    text = text
                                            .substring(0, start_loc + index2)
                                            + aDiff.text
                                            + text.substring(start_loc + index2);
                                } else if (aDiff.operation == Operation.DELETE) {
                                    // Deletion
                                    text = text
                                            .substring(0, start_loc + index2)
                                            + text.substring(start_loc
                                                    + diff_xIndex(
                                                            diffs,
                                                            index1
                                                                    + aDiff.text
                                                                            .length()));
                                }
                            }
                            if (aDiff.operation != Operation.DELETE) {
                                index1 += aDiff.text.length();
                            }
                        }
                    }
                }
            }
            x++;
        }
        // Strip the padding off.
        text = text.substring(nullPadding.length(),
                text.length() - nullPadding.length());
        return new Object[] { text, results };
    }
public Object [ ] patch_apply ( LinkedList < Patch > patches , String text ) { if ( patches . isEmpty ( ) ) { return new Object [ ] { text , new boolean [ 0 ] } ; } patches = patch_deepCopy ( patches ) ; String nullPadding = patch_addPadding ( patches ) ; text = nullPadding + text + nullPadding ; patch_splitMax ( patches ) ; int x = 0 ; int delta = 0 ; boolean [ ] results = new boolean [ patches . size ( ) ] ; for ( Patch aPatch : patches ) { int expected_loc = aPatch . start2 + delta ; String text1 = diff_text1 ( aPatch . diffs ) ; int start_loc ; int end_loc = - 1 ; if ( text1 . length ( ) > Match_MaxBits ) { start_loc = match_main ( text , text1 . substring ( 0 , Match_MaxBits ) , expected_loc ) ; if ( start_loc != - 1 ) { end_loc = match_main ( text , text1 . substring ( text1 . length ( ) - Match_MaxBits ) , expected_loc + text1 . length ( ) - Match_MaxBits ) ; if ( end_loc == - 1 || start_loc >= end_loc ) { start_loc = - 1 ; } } } else { start_loc = match_main ( text , text1 , expected_loc ) ; } if ( start_loc == - 1 ) { results [ x ] = false ; delta -= aPatch . length2 - aPatch . length1 ; } else { results [ x ] = true ; delta = start_loc - expected_loc ; String text2 ; if ( end_loc == - 1 ) { text2 = text . substring ( start_loc , Math . min ( start_loc + text1 . length ( ) , text . length ( ) ) ) ; } else { text2 = text . substring ( start_loc , Math . min ( end_loc + Match_MaxBits , text . length ( ) ) ) ; } if ( text1 . equals ( text2 ) ) { text = text . substring ( 0 , start_loc ) + diff_text2 ( aPatch . diffs ) + text . substring ( start_loc + text1 . length ( ) ) ; } else { LinkedList < Diff > diffs = diff_main ( text1 , text2 , false ) ; if ( text1 . length ( ) > Match_MaxBits && diff_levenshtein ( diffs ) / ( float ) text1 . length ( ) > Patch_DeleteThreshold ) { results [ x ] = false ; } else { diff_cleanupSemanticLossless ( diffs ) ; int index1 = 0 ; for ( Diff aDiff : aPatch . diffs ) { if ( aDiff . operation != Operation . EQUAL ) { int index2 = diff_xIndex ( diffs , index1 ) ; if ( aDiff . operation == Operation . INSERT ) { text = text . substring ( 0 , start_loc + index2 ) + aDiff . text + text . substring ( start_loc + index2 ) ; } else if ( aDiff . operation == Operation . DELETE ) { text = text . substring ( 0 , start_loc + index2 ) + text . substring ( start_loc + diff_xIndex ( diffs , index1 + aDiff . text . length ( ) ) ) ; } } if ( aDiff . operation != Operation . DELETE ) { index1 += aDiff . text . length ( ) ; } } } } } x ++ ; } text = text . substring ( nullPadding . length ( ) , text . length ( ) - nullPadding . length ( ) ) ; return new Object [ ] { text , results } ; }
Merge a set of patches onto the text. Return a patched text, as well as
an array of true/false values indicating which patches were applied.

@param patches
Array of Patch objects
@param text
Old text.
@return Two element Object array, containing the new text and an array of
boolean values.