Replace.java 7.84 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.text;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Iterator;

public class Replace {
    private static final Logger log = LoggerFactory.getLogger(Replace.class);
    public static final int REPLACE_NONE = 0;
    public static final int REPLACE_IGNORE_HTML = 1;
    public static final int REPLACE_WHOLE_WORD = 2;
    private int flags = 0;
    private ArrayList patterns = new ArrayList();

    public String replace(String source) {
        return this.replace(source, 0);
    }

    public String replace(String source, int wref) {
        log.debug("replace: String \"{}\" with weight reference {}", (Object)source, (Object)new Integer(wref));
        if (source == null || source.length() == 0) {
            return "";
        }
        if (this.patterns.size() == 0) {
            return source;
        }
        char[] src = source.toCharArray();
        Occurrence[] occ = this.getOccurrences(src);
        this.processOccurrences(occ, wref);
        return this.doReplace(src, occ);
    }

    public void setFlags(int flags) {
        this.flags = flags;
    }

    public int getFlags() {
        return this.flags;
    }

    public void addPattern(int pos, String pattern, String replacement) {
        log.debug("addPattern: adding pattern \"{}\" to be replaced by \"{}\" as #{}", new Object[]{pattern, replacement, new Integer(pos)});
        this.patterns.add(pos, new Pattern(pattern, replacement));
    }

    public void addPattern(String pattern, String replacement) {
        this.addPattern(this.patterns.size(), pattern, replacement);
    }

    public void addPatterns(String[][] prPairs) {
        for (int i = 0; i < prPairs.length; ++i) {
            String[] pair = prPairs[i];
            if (pair == null || pair.length < 2) continue;
            this.addPattern(this.patterns.size(), pair[0], pair[1]);
        }
    }

    public Iterator getPatterns() {
        return this.patterns.iterator();
    }

    private final boolean isWordDelim(char c) {
        return c == '\u0000' || c == '/' || c == ' ' || c == '\r' || c == '\n' || c == '\t' || c == '.' || c == ';' || c == '(' || c == ')' || c == ',' || c == '<' || c == '\"' || c == '\\';
    }

    private Occurrence[] getOccurrences(char[] src) {
        log.debug("getOccurrences: Getting all occurrences according to the flags {}", (Object)Integer.toHexString(this.flags));
        boolean insidetag = false;
        boolean reinit = true;
        ArrayList<Occurrence> occ = new ArrayList<Occurrence>();
        int srclen = src.length;
        for (int i = 0; i < srclen; ++i) {
            char c = src[i];
            if (c == '<' && (this.flags & 1) != 0 && !insidetag) {
                log.debug("Starting an ignored HTML tag at pos " + i);
                insidetag = true;
                continue;
            }
            if (insidetag) {
                if (c != '>') continue;
                log.debug("Ending an ignored HTML tag at pos " + i);
                insidetag = false;
                reinit = true;
                continue;
            }
            for (Pattern pat : this.patterns) {
                int pos;
                if (pat.len == 0) continue;
                int n = pos = reinit ? 0 : pat.pos;
                while (pos > -1 && pat.pattern[pos] != c) {
                    pos = pat.shift[pos];
                }
                if (++pos >= pat.len) {
                    int beg = i - pos + 1;
                    int end = i - pos + pat.len;
                    boolean valid = true;
                    if ((this.flags & 2) != 0) {
                        char b = beg > 0 ? src[beg - 1] : '\u0000';
                        char e = src[end + 1];
                        boolean bl = valid = this.isWordDelim(b) && this.isWordDelim(e);
                    }
                    if (valid) {
                        log.debug("Found pattern \"{}\" at position {}", (Object)pat.pattern, (Object)new Integer(beg + 1));
                        occ.add(new Occurrence(beg, end, pat));
                    } else {
                        log.debug("Ignoring pattern \"{}\" at position {}", (Object)pat.pattern, (Object)new Integer(beg + 1));
                    }
                    pos = pat.shift[pos];
                }
                pat.pos = pos;
            }
            reinit = false;
        }
        log.debug("Found " + occ.size() + " occurrences");
        return occ.toArray(new Occurrence[occ.size()]);
    }

    private void processOccurrences(Occurrence[] occ, int wref) {
        int awref = Math.abs(wref);
        int numOccs = occ.length;
        log.debug("Detecting collisions on " + occ.length + " patterns");
        for (int i = 0; i < numOccs; ++i) {
            if (occ[i].pattern == null) {
                log.debug("The occurrence has been invalidated: #{}, [{}-{}]", new Object[]{new Integer(i), new Integer(occ[i].begin), new Integer(occ[i].end)});
                continue;
            }
            int best = i;
            int weight = Math.abs(occ[i].pattern.weight - awref);
            for (int p = i + 1; p < numOccs && occ[p].begin <= occ[i].end; ++p) {
                if (occ[p].pattern == null || (occ[i].end < occ[p].begin || occ[i].end > occ[p].end) && (occ[p].begin < occ[i].begin || occ[p].begin > occ[i].end)) continue;
                int pweight = Math.abs(occ[p].pattern.weight - awref);
                if (wref >= 0) continue;
                if (pweight < weight) {
                    weight = pweight;
                    occ[best].pattern = null;
                    best = p;
                } else {
                    occ[p].pattern = null;
                }
                if (pweight > weight) {
                    weight = pweight;
                    occ[best].pattern = null;
                    best = p;
                    continue;
                }
                occ[p].pattern = null;
            }
        }
    }

    private String doReplace(char[] src, Occurrence[] occ) {
        StringBuffer dest = new StringBuffer(src.length);
        int p = 0;
        log.debug("Doing the replacment of all valid occurrences");
        for (int i = 0; i < occ.length; ++i) {
            if (occ[i].pattern == null) continue;
            log.debug("Replacing \"{}\" by \"{}\" @{}", new Object[]{occ[i].pattern.pattern, occ[i].pattern.replace, new Integer(occ[i].begin)});
            dest.append(src, p, occ[i].begin - p);
            dest.append(occ[i].pattern.replace);
            p = occ[i].end + 1;
        }
        if (p < src.length) {
            dest.append(src, p, src.length - p);
        }
        return dest.toString();
    }

    private static final class Occurrence {
        public int begin;
        public int end;
        public Pattern pattern;

        public Occurrence(int begin, int end, Pattern pattern) {
            this.begin = begin;
            this.end = end;
            this.pattern = pattern;
        }
    }

    private static final class Pattern {
        public char[] pattern;
        public String replace;
        public int[] shift;
        public int pos;
        public int len;
        public int weight;

        public Pattern(String pattern, String replace) {
            this.pattern = pattern.toCharArray();
            this.len = pattern.length();
            this.replace = replace;
            this.shift = new int[this.len + 1];
            this.weight = this.len;
            this.shift[0] = -1;
            int j = -1;
            int i = 0;
            while (i < this.len) {
                while (j > -1 && this.pattern[i] != this.pattern[j]) {
                    j = this.shift[j];
                }
                this.shift[i] = ++i < this.len && this.pattern[i] == this.pattern[j] || i == j ? this.shift[j] : ++j;
            }
        }
    }

}