text:
package com.fsck.zywxMailk9.helper;

import android.text.*;
import android.util.Log;

import com.fsck.zywxMailk9.K9;

import org.xml.sax.XMLReader;

import java.io.IOException;
import java.io.StringReader;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Matcher;

/**
 * Contains common routines to convert html to text and vice versa.
 */
public class HtmlConverter {
    /**
     * When generating previews, Spannable objects that can't be converted into a String are
     * represented as 0xfffc. When displayed, these show up as undisplayed squares. These constants
     * define the object character and the replacement character.
     */
    private static final char PREVIEW_OBJECT_CHARACTER = (char)0xfffc;
    private static final char PREVIEW_OBJECT_REPLACEMENT = (char)0x20;  // space

    /**
     * toHtml() converts non-breaking spaces into the UTF-8 non-breaking space, which doesn't get
     * rendered properly in some clients. Replace it with a simple space.
     */
    private static final char NBSP_CHARACTER = (char)0x00a0;    // utf-8 non-breaking space
    private static final char NBSP_REPLACEMENT = (char)0x20;    // space

    // Number of extra bytes to allocate in a string buffer for htmlification.
    private static final int TEXT_TO_HTML_EXTRA_BUFFER_LENGTH = 512;

    /**
     * Convert an HTML string to a plain text string.
     * @param html HTML string to convert.
     * @return Plain text result.
     */
    public static String htmlToText(final String html) {
        return Html.fromHtml(html, null, new HtmlToTextTagHandler()).toString()
               .replace(PREVIEW_OBJECT_CHARACTER, PREVIEW_OBJECT_REPLACEMENT)
               .replace(NBSP_CHARACTER, NBSP_REPLACEMENT);
    }

    /**
     * Custom tag handler to use when converting HTML messages to text. It currently handles text
     * representations of HTML tags that Android's built-in parser doesn't understand and hides code
     * contained in STYLE and SCRIPT blocks.
     */
    private static class HtmlToTextTagHandler implements Html.TagHandler {
        // List of tags whose content should be ignored.
        private static final Set<String> TAGS_WITH_IGNORED_CONTENT;
        static {
            Set<String> set = new HashSet<String>();
            set.add("style");
            set.add("script");
            set.add("title");
            set.add("!");   // comments
            TAGS_WITH_IGNORED_CONTENT = Collections.unmodifiableSet(set);
        }

        @Override
        public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {
            tag = tag.toLowerCase(Locale.US);
            if (tag.equals("hr") && opening) {
                // In the case of an
, replace it with a bunch of underscores. This is roughly
                // the behaviour of Outlook in Rich Text mode.
                output.append("_____________________________________________\n");
            } else if (TAGS_WITH_IGNORED_CONTENT.contains(tag)) {
                handleIgnoredTag(opening, output);
            }
        }

        private static final String IGNORED_ANNOTATION_KEY = "K9_ANNOTATION";
        private static final String IGNORED_ANNOTATION_VALUE = "hiddenSpan";

        /**
         * When we come upon an ignored tag, we mark it with an Annotation object with a specific key
         * and value as above. We don't really need to be checking these values since Html.fromHtml()
         * doesn't use Annotation spans, but we should do it now to be safe in case they do start using
         * it in the future.
         * @param opening If this is an opening tag or not.
         * @param output Spannable string that we're working with.
         */
        private void handleIgnoredTag(boolean opening, Editable output) {
            int len = output.length();
            if (opening) {
                output.setSpan(new Annotation(IGNORED_ANNOTATION_KEY, IGNORED_ANNOTATION_VALUE), len,
                               len, Spannable.SPAN_MARK_MARK);
            } else {
                Object start = getOpeningAnnotation(output);
                if (start != null) {
                    int where = output.getSpanStart(start);
                    // Remove the temporary Annotation span.
                    output.removeSpan(start);
                    // Delete everything between the start of the Annotation and the end of the string
                    // (what we've generated so far).
                    output.delete(where, len);
                }
            }
        }

        /**
         * Fetch the matching opening Annotation object and verify that it's the one added by K9.
         * @param output Spannable string we're working with.
         * @return Starting Annotation object.
         */
        private Object getOpeningAnnotation(Editable output) {
            Object[] objs = output.getSpans(0, output.length(), Annotation.class);
            for (int i = objs.length - 1; i >= 0; i--) {
                Annotation span = (Annotation) objs[i];
                if (output.getSpanFlags(objs[i]) == Spannable.SPAN_MARK_MARK
                        && span.getKey().equals(IGNORED_ANNOTATION_KEY)
                        && span.getValue().equals(IGNORED_ANNOTATION_VALUE)) {
                    return objs[i];
                }
            }
            return null;
        }
    }

    private static final int MAX_SMART_HTMLIFY_MESSAGE_LENGTH = 1024 * 256 ;

    public static final String getHtmlHeader() {
        return "";
    }

    public static final String getHtmlFooter() {
        return "";
    }

    /**
     * Naively convert a text string into an HTML document.
     *
     *

     * This method avoids using regular expressions on the entire message body to save memory.
     *

     *
     * @param text
     *         Plain text string.
     * @param useHtmlTag
     *         If {@code true} this method adds headers and footers to create a proper HTML
     *         document.
     *
     * @return HTML string.
     */
    private static String simpleTextToHtml(String text, boolean useHtmlTag) {
        // Encode HTML entities to make sure we don't display something evil.
        text = TextUtils.htmlEncode(text);

        StringReader reader = new StringReader(text);
        StringBuilder buff = new StringBuilder(text.length() + TEXT_TO_HTML_EXTRA_BUFFER_LENGTH);

        if (useHtmlTag) {
            buff.append(getHtmlHeader());
        }

        buff.append(htmlifyMessageHeader());

        int c;
        try {
            while ((c = reader.read()) != -1) {
                switch (c) {
                case '\n':
                    // pine treats
 as two newlines, but
 as one newline.  Use
 so our messages aren't
                    // doublespaced.
                    buff.append("
");
                    break;
                case '\r':
                    break;
                default:
                    buff.append((char)c);
                }//switch
            }
        } catch (IOException e) {
            //Should never happen
            Log.e(K9.LOG_TAG, "Could not read string to convert text to HTML:", e);
        }

        buff.append(htmlifyMessageFooter());

        if (useHtmlTag) {
            buff.append(getHtmlFooter());
        }

        return buff.toString();
    }

    private static final String HTML_BLOCKQUOTE_COLOR_TOKEN = "$$COLOR$$";
    private static final String HTML_BLOCKQUOTE_START = "
";
    private static final String HTML_BLOCKQUOTE_END = "
";
    private static final String HTML_NEWLINE = "
";

    /**
     * Convert a text string into an HTML document.
     *
     *

     * Attempts to do smart replacement for large documents to prevent OOM errors. This method
     * optionally adds headers and footers to create a proper HTML document. To convert to a
     * fragment, use {@link #textToHtmlFragment(String)}.
     *

     *
     * @param text
     *         Plain text string.
     * @param useHtmlTag
     *         If {@code true} this method adds headers and footers to create a proper HTML
     *         document.
     *
     * @return HTML string.
     */
    public static String textToHtml(String text, boolean useHtmlTag) {
        // Our HTMLification code is somewhat memory intensive
        // and was causing lots of OOM errors on the market
        // if the message is big and plain text, just do
        // a trivial htmlification
        if (text.length() > MAX_SMART_HTMLIFY_MESSAGE_LENGTH) {
            return simpleTextToHtml(text, useHtmlTag);
        }
        StringReader reader = new StringReader(text);
        StringBuilder buff = new StringBuilder(text.length() + TEXT_TO_HTML_EXTRA_BUFFER_LENGTH);
        boolean isStartOfLine = false;  // Are we currently at the start of a line?
        int quoteDepth = 0; // Number of DIVs deep we are.
        int quotesThisLine = 0; // How deep we should be quoting for this line.
        try {
            int c;
            while ((c = reader.read()) != -1) {
                switch (c) {
                case '\n':
                    // pine treats
 as two newlines, but
 as one newline.  Use
 so our messages aren't
                    // doublespaced.
                    buff.append(HTML_NEWLINE);
                    isStartOfLine = true;
                    quotesThisLine = 0;
                    break;
                case '&':
                    buff.append("&");
                    break;
                case '<':
                    buff.append("<");
                    break;
                case '>':
                    if (isStartOfLine) {
                        quotesThisLine++;
                    } else {
                        buff.append(">");
                    }
                    break;
                case '\r':
                    break;
                case ' ':
                    if (isStartOfLine) {
                        // If we're still in the start of the line and we have spaces, don't output them, since they
                        // may be collapsed by our div-converting magic.
                        break;
                    }
                default:
                    if (isStartOfLine) {
                        // Not a quote character and not a space.  Content is starting now.
                        isStartOfLine = false;
                        if (K9.DEBUG) {
                            Log.d(K9.LOG_TAG, "currentQuoteDepth: " + quoteDepth + " quotesThisLine: " + quotesThisLine);
                        }
                        // Add/remove blockquotes by comparing this line's quotes to the previous line's quotes.
                        if (quotesThisLine > quoteDepth) {
                            for (int i = quoteDepth; i < quotesThisLine; i++) {
                                buff.append(HTML_BLOCKQUOTE_START.replace(HTML_BLOCKQUOTE_COLOR_TOKEN, getQuoteColor(i + 1)));
                            }
                        } else if (quotesThisLine < quoteDepth) {
                            for (int i = quoteDepth; i > quotesThisLine; i--) {
                                buff.append(HTML_BLOCKQUOTE_END);
                            }
                        }
                        quoteDepth = quotesThisLine;
                    }
                    buff.append((char)c);
                }//switch
            }
        } catch (IOException e) {
            //Should never happen
            Log.e(K9.LOG_TAG, "Could not read string to convert text to HTML:", e);
        }
        // Close off any quotes we may have opened.
        if (quoteDepth > 0) {
            for (int i = quoteDepth; i > 0; i--) {
                buff.append(HTML_BLOCKQUOTE_END);
            }
        }
        text = buff.toString();

        // Make newlines at the end of blockquotes nicer by putting newlines beyond the first one outside of the
        // blockquote.
        text = text.replaceAll(
                   "\\Q" + HTML_NEWLINE + "\\E((\\Q" + HTML_NEWLINE + "\\E)+?)\\Q" + HTML_BLOCKQUOTE_END + "\\E",
                   HTML_BLOCKQUOTE_END + "$1"
               );

        // Replace lines of -,= or _ with horizontal rules
        text = text.replaceAll("\\s*([-=_]{30,}+)\\s*", "
");

        // TODO: reverse engineer (or troll history) and document
        text = text.replaceAll("(?m)^([^\r\n]{4,}[\\s\\w,:;+/])(?:\r\n|\n|\r)(?=[a-z]\\S{0,10}[\\s\\n\\r])", "$1 ");

        // Compress four or more newlines down to two newlines
        text = text.replaceAll("(?m)(\r\n|\n|\r){4,}", "\n\n");

        StringBuffer sb = new StringBuffer(text.length() + TEXT_TO_HTML_EXTRA_BUFFER_LENGTH);

        if (useHtmlTag) {
            sb.append(getHtmlHeader());
        }

        sb.append(htmlifyMessageHeader());
        linkifyText(text, sb);
        sb.append(htmlifyMessageFooter());

        if (useHtmlTag) {
            sb.append(getHtmlFooter());
        }

        text = sb.toString();

        return text;
    }

    protected static final String QUOTE_COLOR_DEFAULT = "#ccc";
    protected static final String QUOTE_COLOR_LEVEL_1 = "#729fcf";
    protected static final String QUOTE_COLOR_LEVEL_2 = "#ad7fa8";
    protected static final String QUOTE_COLOR_LEVEL_3 = "#8ae234";
    protected static final String QUOTE_COLOR_LEVEL_4 = "#fcaf3e";
    protected static final String QUOTE_COLOR_LEVEL_5 = "#e9b96e";

    /**
     * Return an HTML hex color string for a given quote level.
     * @param level Quote level
     * @return Hex color string with prepended #.
     */
    protected static String getQuoteColor(final int level) {
        switch(level) {
            case 1:
                return QUOTE_COLOR_LEVEL_1;
            case 2:
                return QUOTE_COLOR_LEVEL_2;
            case 3:
                return QUOTE_COLOR_LEVEL_3;
            case 4:
                return QUOTE_COLOR_LEVEL_4;
            case 5:
                return QUOTE_COLOR_LEVEL_5;
            default:
                return QUOTE_COLOR_DEFAULT;
        }
    }

    /**
     * Searches for link-like text in a string and turn it into a link. Append the result to
     * <tt>outputBuffer</tt>. <tt>text</tt> is not modified.
     * @param text Plain text to be linkified.
     * @param outputBuffer Buffer to append linked text to.
     */
    private static void linkifyText(final String text, final StringBuffer outputBuffer) {
        Matcher m = Regex.WEB_URL_PATTERN.matcher(text);
        while (m.find()) {
            int start = m.start();
            if (start == 0 || (start != 0 && text.charAt(start - 1) != '@')) {
                if (m.group().indexOf(':') > 0) { // With no URI-schema we may get "http:/" links with the second / missing
                    m.appendReplacement(outputBuffer, "$0");
                } else {
                    m.appendReplacement(outputBuffer, "$0");
                }
            } else {
                m.appendReplacement(outputBuffer, "$0");
            }
        }

        m.appendTail(outputBuffer);
    }

    /*
     * Lightweight method to check whether the message contains emoji or not.
     * Useful to avoid calling the heavyweight convertEmoji2Img method.
     * We don't use String.codePointAt here for performance reasons.
     */
    private static boolean hasEmoji(String html) {
        for (int i = 0; i = 0xDBB8 && c < 0xDBBC)
                return true;
        }
        return false;
    }

    public static String convertEmoji2Img(String html) {
        if (!hasEmoji(html)) {
            return html;

        }
        StringBuilder buff = new StringBuilder(html.length() + 512);
        for (int i = 0; i < html.length(); i = html.offsetByCodePoints(i, 1)) {
            int codePoint = html.codePointAt(i);
            String emoji = getEmojiForCodePoint(codePoint);
            if (emoji != null)
                buff.append("");
            else
                buff.appendCodePoint(codePoint);

        }
        return buff.toString();
    }

    private static String getEmojiForCodePoint(int codePoint) {
        // Derived from http://code.google.com/p/emoji4unicode/source/browse/trunk/data/emoji4unicode.xml
        // XXX: This doesn't cover all the characters.  More emoticons are wanted.
        switch (codePoint) {
        case 0xFE000:
            return "sun";
        case 0xFE001:
            return "cloud";
        case 0xFE002:
            return "rain";
        case 0xFE003:
            return "snow";
        case 0xFE004:
            return "thunder";
        case 0xFE005:
            return "typhoon";
        case 0xFE006:
            return "mist";
        case 0xFE007:
            return "sprinkle";
        case 0xFE008:
            return "night";
        case 0xFE009:
            return "sun";
        case 0xFE00A:
            return "sun";
        case 0xFE00C:
            return "sun";
        case 0xFE010:
            return "night";
        case 0xFE011:
            return "newmoon";
        case 0xFE012:
            return "moon1";
        case 0xFE013:
            return "moon2";
        case 0xFE014:
            return "moon3";
        case 0xFE015:
            return "fullmoon";
        case 0xFE016:
            return "moon2";
        case 0xFE018:
            return "soon";
        case 0xFE019:
            return "on";
        case 0xFE01A:
            return "end";
        case 0xFE01B:
            return "sandclock";
        case 0xFE01C:
            return "sandclock";
        case 0xFE01D:
            return "watch";
        case 0xFE01E:
            return "clock";
        case 0xFE01F:
            return "clock";
        case 0xFE020:
            return "clock";
        case 0xFE021:
            return "clock";
        case 0xFE022:
            return "clock";
        case 0xFE023:
            return "clock";
        case 0xFE024:
            return "clock";
        case 0xFE025:
            return "clock";
        case 0xFE026:
            return "clock";
        case 0xFE027:
            return "clock";
        case 0xFE028:
            return "clock";
        case 0xFE029:
            return "clock";
        case 0xFE02A:
            return "clock";
        case 0xFE02B:
            return "aries";
        case 0xFE02C:
            return "taurus";
        case 0xFE02D:
            return "gemini";
        case 0xFE02E:
            return "cancer";
        case 0xFE02F:
            return "leo";
        case 0xFE030:
            return "virgo";
        case 0xFE031:
            return "libra";
        case 0xFE032:
            return "scorpius";
        case 0xFE033:
            return "sagittarius";
        case 0xFE034:
            return "capricornus";
        case 0xFE035:
            return "aquarius";
        case 0xFE036:
            return "pisces";
        case 0xFE038:
            return "wave";
        case 0xFE03B:
            return "night";
        case 0xFE03C:
            return "clover";
        case 0xFE03D:
            return "tulip";
        case 0xFE03E:
            return "bud";
        case 0xFE03F:
            return "maple";
        case 0xFE040:
            return "cherryblossom";
        case 0xFE042:
            return "maple";
        case 0xFE04E:
            return "clover";
        case 0xFE04F:
            return "cherry";
        case 0xFE050:
            return "banana";
        case 0xFE051:
            return "apple";
        case 0xFE05B:
            return "apple";
        case 0xFE190:
            return "eye";
        case 0xFE191:
            return "ear";
        case 0xFE193:
            return "kissmark";
        case 0xFE194:
            return "bleah";
        case 0xFE195:
            return "rouge";
        case 0xFE198:
            return "hairsalon";
        case 0xFE19A:
            return "shadow";
        case 0xFE19B:
            return "happy01";
        case 0xFE19C:
            return "happy01";
        case 0xFE19D:
            return "happy01";
        case 0xFE19E:
            return "happy01";
        case 0xFE1B7:
            return "dog";
        case 0xFE1B8:
            return "cat";
        case 0xFE1B9:
            return "snail";
        case 0xFE1BA:
            return "chick";
        case 0xFE1BB:
            return "chick";
        case 0xFE1BC:
            return "penguin";
        case 0xFE1BD:
            return "fish";
        case 0xFE1BE:
            return "horse";
        case 0xFE1BF:
            return "pig";
        case 0xFE1C8:
            return "chick";
        case 0xFE1C9:
            return "fish";
        case 0xFE1CF:
            return "aries";
        case 0xFE1D0:
            return "dog";
        case 0xFE1D8:
            return "dog";
        case 0xFE1D9:
            return "fish";
        case 0xFE1DB:
            return "foot";
        case 0xFE1DD:
            return "chick";
        case 0xFE1E0:
            return "pig";
        case 0xFE1E3:
            return "cancer";
        case 0xFE320:
            return "angry";
        case 0xFE321:
            return "sad";
        case 0xFE322:
            return "wobbly";
        case 0xFE323:
            return "despair";
        case 0xFE324:
            return "wobbly";
        case 0xFE325:
            return "coldsweats02";
        case 0xFE326:
            return "gawk";
        case 0xFE327:
            return "lovely";
        case 0xFE328:
            return "smile";
        case 0xFE329:
            return "bleah";
        case 0xFE32A:
            return "bleah";
        case 0xFE32B:
            return "delicious";
        case 0xFE32C:
            return "lovely";
        case 0xFE32D:
            return "lovely";
        case 0xFE32F:
            return "happy02";
        case 0xFE330:
            return "happy01";
        case 0xFE331:
            return "coldsweats01";
        case 0xFE332:
            return "happy02";
        case 0xFE333:
            return "smile";
        case 0xFE334:
            return "happy02";
        case 0xFE335:
            return "delicious";
        case 0xFE336:
            return "happy01";
        case 0xFE337:
            return "happy01";
        case 0xFE338:
            return "coldsweats01";
        case 0xFE339:
            return "weep";
        case 0xFE33A:
            return "crying";
        case 0xFE33B:
            return "shock";
        case 0xFE33C:
            return "bearing";
        case 0xFE33D:
            return "pout";
        case 0xFE33E:
            return "confident";
        case 0xFE33F:
            return "sad";
        case 0xFE340:
            return "think";
        case 0xFE341:
            return "shock";
        case 0xFE342:
            return "sleepy";
        case 0xFE343:
            return "catface";
        case 0xFE344:
            return "coldsweats02";
        case 0xFE345:
            return "coldsweats02";
        case 0xFE346:
            return "bearing";
        case 0xFE347:
            return "wink";
        case 0xFE348:
            return "happy01";
        case 0xFE349:
            return "smile";
        case 0xFE34A:
            return "happy02";
        case 0xFE34B:
            return "lovely";
        case 0xFE34C:
            return "lovely";
        case 0xFE34D:
            return "weep";
        case 0xFE34E:
            return "pout";
        case 0xFE34F:
            return "smile";
        case 0xFE350:
            return "sad";
        case 0xFE351:
            return "ng";
        case 0xFE352:
            return "ok";
        case 0xFE357:
            return "paper";
        case 0xFE359:
            return "sad";
        case 0xFE35A:
            return "angry";
        case 0xFE4B0:
            return "house";
        case 0xFE4B1:
            return "house";
        case 0xFE4B2:
            return "building";
        case 0xFE4B3:
            return "postoffice";
        case 0xFE4B4:
            return "hospital";
        case 0xFE4B5:
            return "bank";
        case 0xFE4B6:
            return "atm";
        case 0xFE4B7:
            return "hotel";
        case 0xFE4B9:
            return "24hours";
        case 0xFE4BA:
            return "school";
        case 0xFE4C1:
            return "ship";
        case 0xFE4C2:
            return "bottle";
        case 0xFE4C3:
            return "fuji";
        case 0xFE4C9:
            return "wrench";
        case 0xFE4CC:
            return "shoe";
        case 0xFE4CD:
            return "shoe";
        case 0xFE4CE:
            return "eyeglass";
        case 0xFE4CF:
            return "t-shirt";
        case 0xFE4D0:
            return "denim";
        case 0xFE4D1:
            return "crown";
        case 0xFE4D2:
            return "crown";
        case 0xFE4D6:
            return "boutique";
        case 0xFE4D7:
            return "boutique";
        case 0xFE4DB:
            return "t-shirt";
        case 0xFE4DC:
            return "moneybag";
        case 0xFE4DD:
            return "dollar";
        case 0xFE4E0:
            return "dollar";
        case 0xFE4E2:
            return "yen";
        case 0xFE4E3:
            return "dollar";
        case 0xFE4EF:
            return "camera";
        case 0xFE4F0:
            return "bag";
        case 0xFE4F1:
            return "pouch";
        case 0xFE4F2:
            return "bell";
        case 0xFE4F3:
            return "door";
        case 0xFE4F9:
            return "movie";
        case 0xFE4FB:
            return "flair";
        case 0xFE4FD:
            return "sign05";
        case 0xFE4FF:
            return "book";
        case 0xFE500:
            return "book";
        case 0xFE501:
            return "book";
        case 0xFE502:
            return "book";
        case 0xFE503:
            return "book";
        case 0xFE505:
            return "spa";
        case 0xFE506:
            return "toilet";
        case 0xFE507:
            return "toilet";
        case 0xFE508:
            return "toilet";
        case 0xFE50F:
            return "ribbon";
        case 0xFE510:
            return "present";
        case 0xFE511:
            return "birthday";
        case 0xFE512:
            return "xmas";
        case 0xFE522:
            return "pocketbell";
        case 0xFE523:
            return "telephone";
        case 0xFE524:
            return "telephone";
        case 0xFE525:
            return "mobilephone";
        case 0xFE526:
            return "phoneto";
        case 0xFE527:
            return "memo";
        case 0xFE528:
            return "faxto";
        case 0xFE529:
            return "mail";
        case 0xFE52A:
            return "mailto";
        case 0xFE52B:
            return "mailto";
        case 0xFE52C:
            return "postoffice";
        case 0xFE52D:
            return "postoffice";
        case 0xFE52E:
            return "postoffice";
        case 0xFE535:
            return "present";
        case 0xFE536:
            return "pen";
        case 0xFE537:
            return "chair";
        case 0xFE538:
            return "pc";
        case 0xFE539:
            return "pencil";
        case 0xFE53A:
            return "clip";
        case 0xFE53B:
            return "bag";
        case 0xFE53E:
            return "hairsalon";
        case 0xFE540:
            return "memo";
        case 0xFE541:
            return "memo";
        case 0xFE545:
            return "book";
        case 0xFE546:
            return "book";
        case 0xFE547:
            return "book";
        case 0xFE548:
            return "memo";
        case 0xFE54D:
            return "book";
        case 0xFE54F:
            return "book";
        case 0xFE552:
            return "memo";
        case 0xFE553:
            return "foot";
        case 0xFE7D0:
            return "sports";
        case 0xFE7D1:
            return "baseball";
        case 0xFE7D2:
            return "golf";
        case 0xFE7D3:
            return "tennis";
        case 0xFE7D4:
            return "soccer";
        case 0xFE7D5:
            return "ski";
        case 0xFE7D6:
            return "basketball";
        case 0xFE7D7:
            return "motorsports";
        case 0xFE7D8:
            return "snowboard";
        case 0xFE7D9:
            return "run";
        case 0xFE7DA:
            return "snowboard";
        case 0xFE7DC:
            return "horse";
        case 0xFE7DF:
            return "train";
        case 0xFE7E0:
            return "subway";
        case 0xFE7E1:
            return "subway";
        case 0xFE7E2:
            return "bullettrain";
        case 0xFE7E3:
            return "bullettrain";
        case 0xFE7E4:
            return "car";
        case 0xFE7E5:
            return "rvcar";
        case 0xFE7E6:
            return "bus";
        case 0xFE7E8:
            return "ship";
        case 0xFE7E9:
            return "airplane";
        case 0xFE7EA:
            return "yacht";
        case 0xFE7EB:
            return "bicycle";
        case 0xFE7EE:
            return "yacht";
        case 0xFE7EF:
            return "car";
        case 0xFE7F0:
            return "run";
        case 0xFE7F5:
            return "gasstation";
        case 0xFE7F6:
            return "parking";
        case 0xFE7F7:
            return "signaler";
        case 0xFE7FA:
            return "spa";
        case 0xFE7FC:
            return "carouselpony";
        case 0xFE7FF:
            return "fish";
        case 0xFE800:
            return "karaoke";
        case 0xFE801:
            return "movie";
        case 0xFE802:
            return "movie";
        case 0xFE803:
            return "music";
        case 0xFE804:
            return "art";
        case 0xFE805:
            return "drama";
        case 0xFE806:
            return "event";
        case 0xFE807:
            return "ticket";
        case 0xFE808:
            return "slate";
        case 0xFE809:
            return "drama";
        case 0xFE80A:
            return "game";
        case 0xFE813:
            return "note";
        case 0xFE814:
            return "notes";
        case 0xFE81A:
            return "notes";
        case 0xFE81C:
            return "tv";
        case 0xFE81D:
            return "cd";
        case 0xFE81E:
            return "cd";
        case 0xFE823:
            return "kissmark";
        case 0xFE824:
            return "loveletter";
        case 0xFE825:
            return "ring";
        case 0xFE826:
            return "ring";
        case 0xFE827:
            return "kissmark";
        case 0xFE829:
            return "heart02";
        case 0xFE82B:
            return "freedial";
        case 0xFE82C:
            return "sharp";
        case 0xFE82D:
            return "mobaq";
        case 0xFE82E:
            return "one";
        case 0xFE82F:
            return "two";
        case 0xFE830:
            return "three";
        case 0xFE831:
            return "four";
        case 0xFE832:
            return "five";
        case 0xFE833:
            return "six";
        case 0xFE834:
            return "seven";
        case 0xFE835:
            return "eight";
        case 0xFE836:
            return "nine";
        case 0xFE837:
            return "zero";
        case 0xFE960:
            return "fastfood";
        case 0xFE961:
            return "riceball";
        case 0xFE962:
            return "cake";
        case 0xFE963:
            return "noodle";
        case 0xFE964:
            return "bread";
        case 0xFE96A:
            return "noodle";
        case 0xFE973:
            return "typhoon";
        case 0xFE980:
            return "restaurant";
        case 0xFE981:
            return "cafe";
        case 0xFE982:
            return "bar";
        case 0xFE983:
            return "beer";
        case 0xFE984:
            return "japanesetea";
        case 0xFE985:
            return "bottle";
        case 0xFE986:
            return "wine";
        case 0xFE987:
            return "beer";
        case 0xFE988:
            return "bar";
        case 0xFEAF0:
            return "upwardright";
        case 0xFEAF1:
            return "downwardright";
        case 0xFEAF2:
            return "upwardleft";
        case 0xFEAF3:
            return "downwardleft";
        case 0xFEAF4:
            return "up";
        case 0xFEAF5:
            return "down";
        case 0xFEAF6:
            return "leftright";
        case 0xFEAF7:
            return "updown";
        case 0xFEB04:
            return "sign01";
        case 0xFEB05:
            return "sign02";
        case 0xFEB06:
            return "sign03";
        case 0xFEB07:
            return "sign04";
        case 0xFEB08:
            return "sign05";
        case 0xFEB0B:
            return "sign01";
        case 0xFEB0C:
            return "heart01";
        case 0xFEB0D:
            return "heart02";
        case 0xFEB0E:
            return "heart03";
        case 0xFEB0F:
            return "heart04";
        case 0xFEB10:
            return "heart01";
        case 0xFEB11:
            return "heart02";
        case 0xFEB12:
            return "heart01";
        case 0xFEB13:
            return "heart01";
        case 0xFEB14:
            return "heart01";
        case 0xFEB15:
            return "heart01";
        case 0xFEB16:
            return "heart01";
        case 0xFEB17:
            return "heart01";
        case 0xFEB18:
            return "heart02";
        case 0xFEB19:
            return "cute";
        case 0xFEB1A:
            return "heart";
        case 0xFEB1B:
            return "spade";
        case 0xFEB1C:
            return "diamond";
        case 0xFEB1D:
            return "club";
        case 0xFEB1E:
            return "smoking";
        case 0xFEB1F:
            return "nosmoking";
        case 0xFEB20:
            return "wheelchair";
        case 0xFEB21:
            return "free";
        case 0xFEB22:
            return "flag";
        case 0xFEB23:
            return "danger";
        case 0xFEB26:
            return "ng";
        case 0xFEB27:
            return "ok";
        case 0xFEB28:
            return "ng";
        case 0xFEB29:
            return "copyright";
        case 0xFEB2A:
            return "tm";
        case 0xFEB2B:
            return "secret";
        case 0xFEB2C:
            return "recycle";
        case 0xFEB2D:
            return "r-mark";
        case 0xFEB2E:
            return "ban";
        case 0xFEB2F:
            return "empty";
        case 0xFEB30:
            return "pass";
        case 0xFEB31:
            return "full";
        case 0xFEB36:
            return "new";
        case 0xFEB44:
            return "fullmoon";
        case 0xFEB48:
            return "ban";
        case 0xFEB55:
            return "cute";
        case 0xFEB56:
            return "flair";
        case 0xFEB57:
            return "annoy";
        case 0xFEB58:
            return "bomb";
        case 0xFEB59:
            return "sleepy";
        case 0xFEB5A:
            return "impact";
        case 0xFEB5B:
            return "sweat01";
        case 0xFEB5C:
            return "sweat02";
        case 0xFEB5D:
            return "dash";
        case 0xFEB5F:
            return "sad";
        case 0xFEB60:
            return "shine";
        case 0xFEB61:
            return "cute";
        case 0xFEB62:
            return "cute";
        case 0xFEB63:
            return "newmoon";
        case 0xFEB64:
            return "newmoon";
        case 0xFEB65:
            return "newmoon";
        case 0xFEB66:
            return "newmoon";
        case 0xFEB67:
            return "newmoon";
        case 0xFEB77:
            return "shine";
        case 0xFEB81:
            return "id";
        case 0xFEB82:
            return "key";
        case 0xFEB83:
            return "enter";
        case 0xFEB84:
            return "clear";
        case 0xFEB85:
            return "search";
        case 0xFEB86:
            return "key";
        case 0xFEB87:
            return "key";
        case 0xFEB8A:
            return "key";
        case 0xFEB8D:
            return "search";
        case 0xFEB90:
            return "key";
        case 0xFEB91:
            return "recycle";
        case 0xFEB92:
            return "mail";
        case 0xFEB93:
            return "rock";
        case 0xFEB94:
            return "scissors";
        case 0xFEB95:
            return "paper";
        case 0xFEB96:
            return "punch";
        case 0xFEB97:
            return "good";
        case 0xFEB9D:
            return "paper";
        case 0xFEB9F:
            return "ok";
        case 0xFEBA0:
            return "down";
        case 0xFEBA1:
            return "paper";
        case 0xFEE10:
            return "info01";
        case 0xFEE11:
            return "info02";
        case 0xFEE12:
            return "by-d";
        case 0xFEE13:
            return "d-point";
        case 0xFEE14:
            return "appli01";
        case 0xFEE15:
            return "appli02";
        case 0xFEE1C:
            return "movie";
        default:
            return null;
        }
    }

    private static String htmlifyMessageHeader() {
        final String font = K9.messageViewFixedWidthFont()
                            ? "monospace"
                            : "sans-serif";
        return "
";
    }

    private static String htmlifyMessageFooter() {
        return "
";
    }

    /**
     * Convert a plain text string into an HTML fragment.
     * @param text Plain text.
     * @return HTML fragment.
     */
    public static String textToHtmlFragment(final String text) {
        // Escape the entities and add newlines.
        String htmlified = TextUtils.htmlEncode(text);

        // Linkify the message.
        StringBuffer linkified = new StringBuffer(htmlified.length() + TEXT_TO_HTML_EXTRA_BUFFER_LENGTH);
        linkifyText(htmlified, linkified);

        // Add newlines and unescaping.
        //
        // For some reason, TextUtils.htmlEncode escapes ' into ', which is technically part of the XHTML 1.0
        // standard, but Gmail doesn't recognize it as an HTML entity. We unescape that here.
        return linkified.toString().replace("\n", "
\n").replace("'", "'");
    }
}


text:
import {getAllComponents,getComponent,addComponent,addComponentVersion,saveComponent,validateComponent} from "./componentData";
import {initComponentIO} from "./componentIO";
import {initComponentSetup} from "./componentSetup";
import {initComponentEnv} from "./componentEnv";
import {notify,confirm} from "../common/notify";
import {loading} from "../common/loading";

export let allComponents;

export let componentData;
let componentDataOriginalCopy;
let componentName, componentVersion,componentVersionID;

export function initComponentPage(){
    var promise = getAllComponents();
    promise.done(function(data){
        loading.hide();
        allComponents = data.list;
        if(allComponents.length>0){
            showComponentList();
        }else{
            showNoComponent();
        }
    });
    promise.fail(function(xhr,status,error){
        loading.hide();
        if (!_.isUndefined(xhr.responseJSON) && xhr.responseJSON.errMsg) {
            notify(xhr.responseJSON.errMsg,"error");
        }else if(xhr.statusText != "abort"){
            notify("Server is unreachable","error");
        }
    });
}

function showComponentList(){
    $.ajax({
        url: "../../templates/component/componentList.html",
        type: "GET",
        cache: false,
        success: function (data) {
            $("#main").html($(data));
            $("#componentlist").show("slow");

            $(".newcomponent").on('click',function(){
                showNewComponent();
            })

            $(".componentlist_body").empty();
            _.each(allComponents,function(item){
                var pprow = `

                                    <span class="glyphicon glyphicon-menu-down treeclose treecontroller" data-name=`
                                    + item.name +`></span><span style="margin-left:10px">`
                                    + item.name
                                +`</span></td><td></td><td></td></tr>`;
                $(".componentlist_body").append(pprow);

                _.each(item.version,function(version){
                    var vrow = `<tr data-pname=` + item.name + ` data-version=` + version.version + ` data-versionid=`
                                + version.id + ` class="ppversion-row">

                                    ` + version.version + `

                                        <button type="button" class="btn btn-success ppview">

                                            View
                                        </button>

`;

                $(".componentlist_body").append(vrow);
                })
            }) ;

            $(".treecontroller").on("click",function(event){
                var target = $(event.currentTarget);
                if(target.hasClass("treeclose")){
                    target.removeClass("glyphicon-menu-down treeclose");
                    target.addClass("glyphicon-menu-right treeopen");

                    var name = target.data("name");
                    $('*[data-pname="'+name+'"]').hide();
                }else{
                    target.addClass("glyphicon-menu-down treeclose");
                    target.removeClass("glyphicon-menu-right treeopen");

                    var name = target.data("name");
                    $('*[data-pname="'+name+'"]').show();
                }
            });

            $(".ppview").on("click",function(event){
                var target = $(event.currentTarget);
                componentName = target.parent().parent().data("pname");
                componentVersion = target.parent().parent().data("version");
                componentVersionID = target.parent().parent().data("versionid");
                getComponentData();
            })
        }
    });
}

function getComponentData(){
    var promise = getComponent(componentName,componentVersionID);
    promise.done(function(data){
        loading.hide();
        componentData = data;
        componentDataOriginalCopy = $.extend(true,{},data);
        showComponentDesigner();
    });
    promise.fail(function(xhr,status,error){
        loading.hide();
        if (!_.isUndefined(xhr.responseJSON) && xhr.responseJSON.errMsg) {
            notify(xhr.responseJSON.errMsg,"error");
        }else if(xhr.statusText != "abort"){
            notify("Server is unreachable","error");
        }
    });
}

function showNoComponent(){
    $.ajax({
        url: "../../templates/component/noComponent.html",
        type: "GET",
        cache: false,
        success: function (data) {
            $("#main").html($(data));
            $("#nocomponent").show("slow");
            $(".newcomponent").on('click',function(){
                showNewComponent();
            })
        }
    });
}

export function showNewComponent(fromWorkflow){
    $.ajax({
        url: "../../templates/component/newComponent.html",
        type: "GET",
        cache: false,
        success: function (data) {
            $("#main").children().hide();
            $("#main").append($(data));
            $("#newcomponent").show("slow");
            $("#newComponentBtn").on('click',function(){
                var promise = addComponent();
                if(promise){
                    promise.done(function(data){
                        loading.hide();
                        notify(data.message,"success");
                        initComponentPage();
                    });
                    promise.fail(function(xhr,status,error){
                        loading.hide();
                        if (!_.isUndefined(xhr.responseJSON) && xhr.responseJSON.errMsg) {
                            notify(xhr.responseJSON.errMsg,"error");
                        }else if(xhr.statusText != "abort"){
                            notify("Server is unreachable","error");
                        }
                    });
                }
            })
            $("#cancelNewComponentBtn").on('click',function(){
                if(fromWorkflow){
                    $(".menu-component").parent().removeClass("active");
                    $(".menu-workflow").parent().addClass("active");
                }
                cancelNewComponentPage();
            })
        }
    });
}

function showComponentDesigner(){
    $.ajax({
        url: "../../templates/component/componentDesign.html",
        type: "GET",
        cache: false,
        success: function (data) {
            $("#main").html($(data));
            $("#componentdesign").show("slow");

            $("#selected_component").text(componentName + " / " + componentVersion);

            $(".backtolist").on('click',function(){
                beforeBackToList();
            });

            $(".savecomponent").on('click',function(){
                saveComponentData();
            });

            $(".newcomponentversion").on('click',function(){
                if(validateComponent(componentData)){
                    showNewComponentVersion();
                }
            });

            $(".newcomponentindesigner").on('click',function(){
                beforeShowNewComponent();
            });

            initComponentEdit();
        }
    });
}

function initComponentEdit(){
    $.ajax({
        url: "../../templates/component/componentEdit.html",
        type: "GET",
        cache: false,
        success: function (data) {
            $("#componentDesigner").html($(data));

            initComponentSetup(componentData);

            initComponentIO(componentData);

            initComponentEnv(componentData);

            // view select init
            $("#action-component-select").select2({
               minimumResultsForSearch: Infinity
            });

            $("#service-type-select").select2({
               minimumResultsForSearch: Infinity
            });
        }
    });
}

function showNewComponentVersion(){
    $.ajax({
        url: "../../templates/component/newComponentVersion.html",
        type: "GET",
        cache: false,
        success: function (data) {
            $("#main").children().hide();
            $("#main").append($(data));
            $("#newcomponentversion").show("slow");

            $("#c-name-newversion").val(componentName);

            $("#newComponentVersionBtn").on('click',function(){
                var promise = addComponentVersion(componentName,componentVersionID,componentData);
                if(promise){
                    promise.done(function(data){
                        loading.hide();
                        notify(data.message,"success");
                        initComponentPage();
                    });
                    promise.fail(function(xhr,status,error){
                        loading.hide();
                        if (!_.isUndefined(xhr.responseJSON) && xhr.responseJSON.errMsg) {
                            notify(xhr.responseJSON.errMsg,"error");
                        }else if(xhr.statusText != "abort"){
                            notify("Server is unreachable","error");
                        }
                    });
                }
            })
            $("#cancelNewComponentVersionBtn").on('click',function(){
                cancelNewComponentVersionPage();
            })
        }
    });

    $("#content").hide();
    $("#nocomponent").hide();
    $("#newcomponent").hide();
    $("#newcomponentversion").show("slow");
}

function cancelNewComponentPage(){
    $("#newcomponent").remove();
    $("#main").children().show("slow");
}

function cancelNewComponentVersionPage(){
    $("#newcomponentversion").remove();
    $("#main").children().show("slow");
}

function beforeBackToList(){
    if(_.isEqual(componentDataOriginalCopy,componentData)){
        initComponentPage();
    }else{
        var actions = [
            {
                "name":"save",
                "label":"Yes",
                "action":function(){
                    saveComponentData(initComponentPage);
                }
            },{
                "name":"back",
                "label":"No",
                "action":function(){
                    initComponentPage();
                }
            }
        ]
        confirm("The component design has been modified, would you like to save the changes before go back to list.","info",actions);
    }
}

function saveComponentData(next){
    if(validateComponent(componentData)){
        var promise = saveComponent(componentName, componentVersion, componentVersionID, componentData);
        promise.done(function(data){
            componentDataOriginalCopy = $.extend(true,{},componentData);
            loading.hide();
            if(!next){
                notify(data.message,"success");
            }else{
                next();
            }
        });
        promise.fail(function(xhr,status,error){
            loading.hide();
            if(!next){
                if (!_.isUndefined(xhr.responseJSON) && xhr.responseJSON.errMsg) {
                    notify(xhr.responseJSON.errMsg,"error");
                }else if(xhr.statusText != "abort"){
                    notify("Server is unreachable","error");
                }
            }else{
                next();
            }
        });
    }
}

function beforeShowNewComponent(){
    if(_.isEqual(componentDataOriginalCopy,componentData)){
        showNewComponent();
    }else{
        var actions = [
            {
                "name":"save",
                "label":"Yes",
                "action":function(){
                    saveComponentData(showNewComponent);
                }
            },{
                "name":"show",
                "label":"No",
                "action":function(){
                    showNewComponent();
                }
            }
        ]
        confirm("The component design has been modified, would you like to save the changes at first.","info",actions);
    }
}

// $("#workflow-select").on('change',function(){
//     showVersionList();
// })
// $("#version-select").on('change',function(){
//     showWorkflow();
// })

// function showWorkflowList(){
//     $("#workflow-select").empty();
//     d3.select("#workflow-select")
//         .selectAll("option")
//         .data(allWorkflows)
//         .enter()
//         .append("option")
//         .attr("value",function(d,i){
//             return d.name;
//         })
//         .text(function(d,i){
//             return d.name;
//         });
//      $("#workflow-select").select2({
//        minimumResultsForSearch: Infinity
//      });
//     showVersionList();
// }

// function showVersionList(){
//     var workflow = $("#workflow-select").val();
//     var versions = _.find(allWorkflows,function(item){
//         return item.name == workflow;
//     }).versions;

//     $("#version-select").empty();
//     d3.select("#version-select")
//         .selectAll("option")
//         .data(versions)
//         .enter()
//         .append("option")
//         .attr("value",function(d,i){
//             return d.version;
//         })
//         .text(function(d,i){
//             return d.version;
//         });
//     $("#version-select").select2({
//        minimumResultsForSearch: Infinity
//      });

//     versions_shown = versions;

//     showWorkflow();
// }

redpajama_set_name: RedPajamaGithub


text:
/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes} checked by tsc
 */
goog.module('test_files.decorator.decorator');var module = module || {id: 'test_files/decorator/decorator.js'};
var external_1 = goog.require('test_files.decorator.external');
const tsickle_forward_declare_1 = goog.forwardDeclare("test_files.decorator.external");
var external2_1 = goog.require('test_files.decorator.external2');
const tsickle_forward_declare_2 = goog.forwardDeclare("test_files.decorator.external2");
/**
 * @param {!Object} a
 * @param {string} b
 * @return {void}
 */
function decorator(a, b) { }
/**
 * \@Annotation
 * @param {!Object} a
 * @param {string} b
 * @return {void}
 */
function annotationDecorator(a, b) { }
/**
 * @param {?} t
 * @return {?}
 */
function classDecorator(t) { return t; }
/**
 * \@Annotation
 * @param {?} t
 * @return {?}
 */
function classAnnotation(t) { return t; }
class DecoratorTest {
    /**
     * @param {!Array<?>} a
     * @param {number} n
     * @param {boolean} b
     * @param {!Promise<string>} promise
     * @param {!Array<string>} arr
     * @param {!tsickle_forward_declare_1.AClass} aClass
     * @param {!tsickle_forward_declare_1.AClass} AClass
     * @param {!tsickle_forward_declare_1.AClass} aRenamedClass
     * @param {!tsickle_forward_declare_1.AClassWithGenerics<string>} aClassWithGenerics
     * @param {!tsickle_forward_declare_1.AType} aType
     * @param {!tsickle_forward_declare_2.OtherClass} otherClass
     * @param {!tsickle_forward_declare_2.OtherClass} anotherClass
     */
    constructor(a, n, b, promise, arr, aClass, AClass, aRenamedClass, aClassWithGenerics, aType, otherClass, anotherClass) { }
    /**
     * @return {number}
     */
    get w() {
        return 1;
    }
}
DecoratorTest.decorators = [
    { type: classAnnotation },
];
/** @nocollapse */
DecoratorTest.ctorParameters = () => [
    { type: Array, },
    null,
    null,
    { type: Promise, },
    { type: Array, },
    { type: external_1.AClass, },
    { type: external_1.AClass, },
    { type: external_1.AClass, },
    { type: external_1.AClassWithGenerics, },
    null,
    { type: external2_1.OtherClass, },
    { type: external_1.ReexportedOtherClass, },
];
DecoratorTest.propDecorators = {
    "w": [{ type: annotationDecorator },],
    "y": [{ type: annotationDecorator },],
};
__decorate([
    decorator,
    __metadata("design:type", Number)
], DecoratorTest.prototype, "x", void 0);
__decorate([
    decorator,
    __metadata("design:type", external_1.AClass)
], DecoratorTest.prototype, "z", void 0);
function DecoratorTest_tsickle_Closure_declarations() {
    /** @type {!Array<{type: !Function, args: (undefined|!Array<?>)}>} */
    DecoratorTest.decorators;
    /**
     * @nocollapse
     * @type {function(): !Array<(null|{type: ?, decorators: (undefined|!Array<{type: !Function, args: (undefined|!Array<?>)}>)})>}
     */
    DecoratorTest.ctorParameters;
    /** @type {!Object<string,!Array<{type: !Function, args: (undefined|!Array<?>)}>>} */
    DecoratorTest.propDecorators;
    /**
     * Some comment
     * @type {number}
     */
    DecoratorTest.prototype.x;
    /** @type {number} */
    DecoratorTest.prototype.y;
    /** @type {!tsickle_forward_declare_1.AClass} */
    DecoratorTest.prototype.z;
}
let DecoratedClass = class DecoratedClass {
};
DecoratedClass = __decorate([
    classDecorator
], DecoratedClass);
function DecoratedClass_tsickle_Closure_declarations() {
    /** @type {string} */
    DecoratedClass.prototype.z;
}


text:
package org.kuali.coeus.sys.framework.model;

import org.apache.commons.lang3.StringUtils;
import org.kuali.coeus.common.framework.person.attr.PersonEditableField;
import org.kuali.coeus.sys.framework.service.KcServiceLocator;
import org.kuali.coeus.sys.framework.validation.SoftError;
import org.kuali.kra.authorization.KraAuthorizationConstants;
import org.kuali.kra.infrastructure.KeyConstants;
import org.kuali.kra.krms.KcKrmsConstants;
import org.kuali.coeus.common.questionnaire.framework.core.MultiQuestionableFormInterface;
import org.kuali.coeus.common.questionnaire.framework.core.QuestionableFormInterface;
import org.kuali.rice.kim.api.KimConstants;
import org.kuali.rice.kns.document.authorization.DocumentAuthorizerBase;
import org.kuali.rice.kns.web.struts.form.KualiTransactionalDocumentFormBase;
import org.kuali.rice.kns.web.ui.ExtraButton;
import org.kuali.rice.krad.document.Document;
import org.kuali.rice.krad.document.authorization.PessimisticLock;
import org.kuali.rice.krad.service.BusinessObjectService;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.KRADConstants;
import org.kuali.rice.krad.util.ObjectUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * This class isbase class for KC Transactional Documents ...
 */
public abstract class KcTransactionalDocumentFormBase extends KualiTransactionalDocumentFormBase {

    private static final long serialVersionUID = 1161569719154606103L;

    protected String actionName;
    protected String navigateTo;

    private boolean viewOnly;
    private boolean popupViewOnly;

    private boolean medusaOpenedDoc;
    private Map<String, Boolean> personEditableFields;

    private List<String> unitRulesMessages = new ArrayList<String>();

    public String getActionName() {
        return actionName;
    }

    public void setActionName(String actionName) {
        this.actionName = actionName;
    }

    public String getNavigateTo() {
        return navigateTo;
    }

    public void setNavigateTo(String navigateTo) {
        this.navigateTo = navigateTo;
    }

    @Override
    public void populate(HttpServletRequest request) {
        super.populate(request);

        // Hack to get panels with add/delete items that are editable after add (Protocol Participants, Special Review) to work correctly with validation.
        // In this scenario, the user adds a couple of correctly formatted items but then changes one of the fields to an incorrect format and saves.  This will
        // cause validation errors, but if the user now tries to delete the errant entry, validation will fail because the validator in the Kuali Request
        // ProcessDefinitionDefinitionor still detects the error in the message map.  We don't want validation to run for a delete method, so we need to clear the current error
        // messages, preventing the validator from running and allowing the delete to go through.
        //
        // This is detected by the existence of "validate0" on the methodToCall property (similar to finding the line number of a delete).
        String methodToCallAttribute = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
        if (StringUtils.contains(methodToCallAttribute, "validate")) {
            String validateParameter = StringUtils.substringBetween(methodToCallAttribute, ".validate", ".");
            if (StringUtils.equals("0", validateParameter)) {
                GlobalVariables.getMessageMap().clearErrorMessages();
            }
        }
    }

    /**
     * Consume SoftErrors (if any) and return the collection
     * @return
     */
    @SuppressWarnings("unchecked")
    public Map<String, Collection<SoftError>> getSoftErrors() {
        return (Map<String, Collection<SoftError>>) GlobalVariables.getUserSession().retrieveObject(KeyConstants.SOFT_ERRORS_KEY);
    }

    public void setupLockRegions() {
        String lockRegion = getLockRegion();
        GlobalVariables.getUserSession().addObject(KraAuthorizationConstants.ACTIVE_LOCK_REGION, (Object)lockRegion);
        boolean activeLockRegionChangedInd = hasActiveLockRegionChanged(getDocument(), lockRegion);
        GlobalVariables.getUserSession().addObject(KraAuthorizationConstants.LOCK_REGION_CHANGE_IND, activeLockRegionChangedInd);
    }

    private boolean hasActiveLockRegionChanged(Document document, String activeLockRegion) {
        if(StringUtils.isNotEmpty(activeLockRegion)) {
            for(PessimisticLock lock: document.getPessimisticLocks()) {
                if(lock.getLockDescriptor()!=null && !lock.getLockDescriptor().contains(activeLockRegion)
                        && lock.getOwnedByUser().getPrincipalId().equals(GlobalVariables.getUserSession().getPrincipalId())) {
                    return true;
                }
            }
        } else if (document.getPessimisticLocks().size()>0) {
            return true;
        }

        return false;
    }

    protected boolean hasModifyProposalPermission(Map editMode) {
        if (editMode != null && editMode.containsKey(KraAuthorizationConstants.ProposalEditMode.MODIFY_PROPOSAL)) {
            String modifyProposalPermission = (String) editMode.get(KraAuthorizationConstants.ProposalEditMode.MODIFY_PROPOSAL);
            return ((ObjectUtils.isNotNull(modifyProposalPermission)) && (DocumentAuthorizerBase.EDIT_MODE_DEFAULT_TRUE_VALUE
                    .equals(modifyProposalPermission)));
        }

        return false;
    }

    protected boolean hasModifyBudgetPermission(Map editMode) {
        String modifyBudgetPermission = "";
        boolean hasModifyBudgetPermission = false;

        if (editMode != null && editMode.containsKey(KraAuthorizationConstants.BudgetEditMode.MODIFY_BUDGET)) {
            modifyBudgetPermission = (String) editMode.get(KraAuthorizationConstants.BudgetEditMode.MODIFY_BUDGET);
            hasModifyBudgetPermission = ((ObjectUtils.isNotNull(modifyBudgetPermission)) && (DocumentAuthorizerBase.EDIT_MODE_DEFAULT_TRUE_VALUE
                    .equals(modifyBudgetPermission)));
        }

        //Included the new addBudget permission as well - For the New AuthZ Framework
        if (!hasModifyBudgetPermission && editMode != null && editMode.containsKey("addBudget")) {
            modifyBudgetPermission = (String) editMode.get("addBudget");
            hasModifyBudgetPermission = ((ObjectUtils.isNotNull(modifyBudgetPermission)) && (DocumentAuthorizerBase.EDIT_MODE_DEFAULT_TRUE_VALUE
                    .equals(modifyBudgetPermission)));
        }

        return hasModifyBudgetPermission;
    }

    protected boolean hasModifyCompletedBudgetPermission(Map editMode) {
        if (editMode != null && editMode.containsKey("modifyCompletedBudgets")) {
            String modifyBudgetPermission = (String) editMode.get("modifyCompletedBudgets");
            editMode.remove("modifyCompletedBudgets");
            return ((ObjectUtils.isNotNull(modifyBudgetPermission)) && (DocumentAuthorizerBase.EDIT_MODE_DEFAULT_TRUE_VALUE
                    .equals(modifyBudgetPermission)));
        }

        return false;
    }

    protected boolean hasModifyNarrativesPermission(Map editMode) {
        if (editMode != null && editMode.containsKey(KraAuthorizationConstants.ProposalEditMode.ADD_NARRATIVES)) {
            String modifyNarrativesPermission = (String) editMode.get(KraAuthorizationConstants.ProposalEditMode.ADD_NARRATIVES);
            return ((ObjectUtils.isNotNull(modifyNarrativesPermission)) && (DocumentAuthorizerBase.EDIT_MODE_DEFAULT_TRUE_VALUE
                    .equals(modifyNarrativesPermission)));
        }

        return false;
    }

    /**
     * Get the Header Dispatch.  This determines the action that will occur
     * when the user switches tabs for a document.  If the user can modify
     * the document, the document is automatically saved.  If not (view-only),
     * then a reload will be executed instead.
     * @return the Header Dispatch action
     */
    public String getHeaderDispatch() {
        return this.getDocumentActions().containsKey(KRADConstants.KUALI_ACTION_CAN_SAVE) ? "save" : "reload";
    }

    protected abstract String getLockRegion();

    protected abstract void setSaveDocumentControl(Map editMode);

    public final boolean isViewOnly() {
        return viewOnly;
    }

    public final void setViewOnly(boolean viewOnly) {
        this.viewOnly = viewOnly;
    }

    public final boolean isPopupViewOnly() {
        return popupViewOnly;
    }

    public final void setPopupViewOnly(boolean popupViewOnly) {
        this.popupViewOnly = popupViewOnly;
    }

    @Override
    public void setDocument(Document document) {
        super.setDocument(document);
        ((KcTransactionalDocumentBase)document).setViewOnly(isViewOnly());
    }

    @Override
    protected abstract String getDefaultDocumentTypeName();

    public boolean isMedusaOpenedDoc() {
        return medusaOpenedDoc;
    }

    public void setMedusaOpenedDoc(boolean medusaOpenedDoc) {
        this.medusaOpenedDoc = medusaOpenedDoc;
    }

    /**
     * This is a utility method to add a new button to the extra buttons
     * collection.
     *
     * @param property
     * @param source
     * @param altText
     */
    protected void addExtraButton(String property, String source, String altText){

        ExtraButton newButton = new ExtraButton();

        newButton.setExtraButtonProperty(property);
        newButton.setExtraButtonSource(source);
        newButton.setExtraButtonAltText(altText);

        extraButtons.add(newButton);
    }

    public Map<String, Boolean> getPersonEditableFields() {
        if (personEditableFields == null) {
            populatePersonEditableFields();
        }
        return personEditableFields;
    }

    public void setPersonEditableFields(Map<String, Boolean> personEditableFields) {
        this.personEditableFields = personEditableFields;
    }

    /**
     * Creates the list of <code>{@link PersonEditableField}</code> field names.
     */
    public void populatePersonEditableFields() {
        // TODO : should refactor this editablefields related to parent class, so it can be shared by other
        // modules

        setPersonEditableFields(new HashMap<String, Boolean>());

        @SuppressWarnings("unchecked")
     //   Collection<PersonEditableField> fields = getBusinessObjectService().findAll(PersonEditableField.class);
        Map fieldValues = new HashMap();
        fieldValues.put("moduleCode", getModuleCode());
        Collection<PersonEditableField> fields = getBusinessObjectService().findMatching(PersonEditableField.class, fieldValues);
        for (PersonEditableField field : fields) {
                getPersonEditableFields().put(field.getFieldName(), Boolean.valueOf(field.isActive()));
        }
    }

    private BusinessObjectService getBusinessObjectService() {
        return KcServiceLocator.getService(BusinessObjectService.class);
    }

    /**
     *
     * This method should be overriden by modules that is using person editable field.
     * @return
     */
    public String getModuleCode() {
        return "0";
    }

    /**
     * This is a duplication of KualiTransactionalDocumentFormBase.populateFalseCheckboxes with the cavet that this function
     * puts a NULL in for fields that contain "answer", which are the field names of radio Y/N buttons for the questionnaire framework.
     * @see org.kuali.rice.kns.web.struts.form.KualiTransactionalDocumentFormBase#populateFalseCheckboxes(javax.servlet.http.HttpServletRequest)
     */
    @Override
    protected void populateFalseCheckboxes(HttpServletRequest request) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        final String checkBoxToResetFieldParam = "checkboxToReset";
        if (parameterMap.get(checkBoxToResetFieldParam) != null) {
            final String[] checkboxesToResetFields = request.getParameterValues("checkboxToReset");
            if (checkboxesToResetFields != null && checkboxesToResetFields.length > 0) {
                for (int i = 0; i < checkboxesToResetFields.length; i++) {
                    String propertyName = (String) checkboxesToResetFields[i];
                    if (!StringUtils.isBlank(propertyName) && parameterMap.get(propertyName) == null) {
                        if (this instanceof QuestionableFormInterface
                                && (StringUtils.startsWithIgnoreCase(propertyName, ((QuestionableFormInterface) this).getQuestionnaireFieldStarter())
                                && StringUtils.containsIgnoreCase(propertyName, ((QuestionableFormInterface) this).getQuestionnaireFieldMiddle())
                                && StringUtils.endsWithIgnoreCase(propertyName, ((QuestionableFormInterface) this).getQuestionnaireFieldEnd())
                                || propertyName.matches(((QuestionableFormInterface) this).getQuestionnaireExpression()))) {
                            populateForProperty(propertyName, null, parameterMap);
                        } else if (this instanceof MultiQuestionableFormInterface) {
                            processMultiQuestionCheckBox(propertyName, parameterMap, (MultiQuestionableFormInterface) this);

                        } else {
                            populateForProperty(propertyName, KimConstants.KIM_ATTRIBUTE_BOOLEAN_FALSE_STR_VALUE_DISPLAY, parameterMap);
                        }
                    } else if (!StringUtils.isBlank(propertyName) && parameterMap.get(propertyName) != null
                            && parameterMap.get(propertyName).length >= 1
                            && parameterMap.get(propertyName)[0].equalsIgnoreCase("on")) {
                        populateForProperty(propertyName, KimConstants.KIM_ATTRIBUTE_BOOLEAN_TRUE_STR_VALUE_DISPLAY, parameterMap);
                    }
                }
            }
        }
    }

    protected void processMultiQuestionCheckBox(String propertyName, Map<String, String[]> parameterMap, MultiQuestionableFormInterface form) {
        boolean checkBoxFound = false;
        int j = 0;
        for (String starter : form.getQuestionnaireFieldStarters()) {
            if (!checkBoxFound && StringUtils.startsWithIgnoreCase(propertyName, starter)
                    && StringUtils.containsIgnoreCase(propertyName, form.getQuestionnaireFieldEnds()[j])
                    && StringUtils.endsWithIgnoreCase(propertyName, form.getQuestionnaireFieldEnds()[j])) {
                populateForProperty(propertyName, null, parameterMap);;
                checkBoxFound = true;
                break;
            }
            j++;
        }
        if (!checkBoxFound) {
            populateForProperty(propertyName, KimConstants.KIM_ATTRIBUTE_BOOLEAN_FALSE_STR_VALUE_DISPLAY, parameterMap);
        }
    }

    public List<String> getUnitRulesMessages() {
        return unitRulesMessages;
    }

    public void setUnitRulesMessages(List<String> unitRulesMessages) {
        this.unitRulesMessages = unitRulesMessages;
    }

    public boolean isUnitRulesErrorsExist() {
        return getUnitRulesErrors().size() > 0;
    }

    public boolean isUnitRulesWarningsExist() {
        return getUnitRulesWarnings().size() > 0;
    }

    public List<String> getUnitRulesErrors() {
        return getUnitRulesMessages(KcKrmsConstants.MESSAGE_TYPE_ERROR);
    }

    public List<String> getUnitRulesWarnings() {
        return getUnitRulesMessages(KcKrmsConstants.MESSAGE_TYPE_WARNING);
    }

    public void clearUnitRulesMessages() {
        this.unitRulesMessages = Collections.emptyList();
    }

    protected List<String> getUnitRulesMessages(String messageType) {
        List<String> messages = new ArrayList<String>();
        for (String message : this.unitRulesMessages) {
            if (StringUtils.substringBefore(message, KcKrmsConstants.MESSAGE_SEPARATOR).equals(messageType)) {
                messages.add(StringUtils.substringAfter(message, KcKrmsConstants.MESSAGE_SEPARATOR));
            }
        }
        return messages;
    }
}


text:
package com.clearlyspam23.GLE.basic.layers.tile.gui.tileset;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.List;

import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;

import com.clearlyspam23.GLE.basic.layers.tile.TilesetGroupNode;
import com.clearlyspam23.GLE.basic.layers.tile.TilesetHandle;
import com.clearlyspam23.GLE.basic.layers.tile.TilesetTileNode;
import com.clearlyspam23.GLE.basic.layers.tile.TilesetTreeNode;
import com.clearlyspam23.GLE.basic.layers.tile.TilesetTreeNode.Type;
import com.clearlyspam23.GLE.basic.layers.tile.resources.BasicTilesetHandle;

public class TilesetLoadPanel extends JPanel implements TilesetViewListener{
	/**
	 *
	 */
	private static final long serialVersionUID = 1L;
	private TilesetTreeViewPanel tilesetViewPanel;
	private TilesetEditPanel tilesetEditPanel;
	private TilesetGroupNode root;

	private TilesetTileNode currentTilesetNode;

	private final JPopupMenu tilePopUp;

	private final JPopupMenu groupPopUp;

	private static final String newLine = System.getProperty("line.separator");

	private int lastId;

	/**
	 * Create the panel.
	 */
	public TilesetLoadPanel() {
		setLayout(new BorderLayout(0, 0));
		tilePopUp = new JPopupMenu();
		JMenuItem button = new JMenuItem("New Tileset");
		button.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent arg0) {
				BasicTilesetHandle h = new BasicTilesetHandle("New Tileset");
				h.setID(++lastId);
				TilesetTileNode tileNode = new TilesetTileNode(h);
				for(int i = 1; !root.getTilesetsByName(tileNode.getName()).isEmpty(); i++){
					tileNode.setName("New Tileset " + i);
				}
				tilesetViewPanel.insertNode(tileNode, true);
				changeToTileset(tileNode);
			}

		});
		tilePopUp.add(button);
		button = new JMenuItem("New Group");
		button.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent arg0) {
				tilesetViewPanel.insertNode(new TilesetGroupNode("New Group"));
			}

		});
		tilePopUp.add(button);

		tilePopUp.add(button);
		button = new JMenuItem("Remove");
		button.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent arg0) {
				if(JOptionPane.showConfirmDialog(TilesetLoadPanel.this, "Are you sure you want to Remove this Tileset?", "Confirm Removal", JOptionPane.OK_CANCEL_OPTION)==JOptionPane.OK_OPTION)
					tilesetViewPanel.removeNode();
			}

		});
		tilePopUp.add(button);

		groupPopUp = new JPopupMenu();
		button = new JMenuItem("New Tileset");
		button.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent arg0) {
				BasicTilesetHandle h = new BasicTilesetHandle("New Tileset");
				h.setID(++lastId);
				TilesetTileNode tileNode = new TilesetTileNode(h);
				for(int i = 1; !root.getTilesetsByName(tileNode.getName()).isEmpty(); i++){
					tileNode.setName("New Tileset " + i);
				}
				tilesetViewPanel.insertNode(tileNode, true);
				changeToTileset(tileNode);
			}

		});
		groupPopUp.add(button);
		button = new JMenuItem("New Group");
		button.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent arg0) {
				tilesetViewPanel.insertNode(new TilesetGroupNode("New Group"));
			}

		});
		groupPopUp.add(button);

		button = new JMenuItem("Remove");
		button.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent arg0) {
				if(JOptionPane.showConfirmDialog(TilesetLoadPanel.this, "Are you sure you want to Remove this group? This will also Remove any children of this group", "Confirm Removal", JOptionPane.OK_CANCEL_OPTION)==JOptionPane.OK_OPTION)
					tilesetViewPanel.removeNode();
			}

		});
		groupPopUp.add(button);

		JScrollPane scrollPane = new JScrollPane();
		add(scrollPane, BorderLayout.WEST);

		tilesetViewPanel = new TilesetTreeViewPanel();
		tilesetViewPanel.setPreferredSize(new Dimension(160, 0));
		scrollPane.setViewportView(tilesetViewPanel);

		tilesetEditPanel = new TilesetEditPanel();
		add(tilesetEditPanel, BorderLayout.CENTER);

	}

//	public TilesetHandle generateTilesetHandle(){
//
//	}

	private boolean finalizeCurrentTileset(boolean silent){
		if(currentTilesetNode!=null){
			String errorMsg;
			BasicTilesetHandle tileset = tilesetEditPanel.getTileset();
			if(!silent&&!(errorMsg=isValidTileset(tileset)).isEmpty()){
				String msg = "The Tileset currently being edited is invalid for the following reason(s) : " + newLine + newLine + errorMsg + newLine + newLine
						+ "If you change Tilesets, this Tileset will not be saved and any changes will be lost." + newLine + newLine + "Change Tilesets Anyways?";
				return JOptionPane.showConfirmDialog(this, msg, "Confirm Tileset Change", JOptionPane.OK_CANCEL_OPTION)==JOptionPane.OK_OPTION;
			}
			currentTilesetNode.setTileset(tileset);
		}
		return true;
	}

	private void changeToTileset(TilesetTileNode handle){
		if(!finalizeCurrentTileset(false)){
			return;
		}
		currentTilesetNode = handle;
		tilesetEditPanel.setToTileset(handle.getTileset());
	}

	public void setToTileset(TilesetGroupNode tilesetTree, int startId){
		lastId = startId;
		root = tilesetTree.cloneAsBasic().getAsGroup();
		currentTilesetNode = null;
		tilesetEditPanel.setToTileset(null);
		tilesetViewPanel.setToTilesets(root, this);
	}

	private boolean isNameUnique(String name){
		return isNameUnique(name, currentTilesetNode.getTileset());
	}

	private boolean isNameUnique(String name, TilesetHandle handle){
		List<TilesetHandle> h = root.getTilesetsByName(name);
		if(h.size()==1){
			return h.get(0)==handle;
		}
		return h.isEmpty();
	}

	private String isValidTileset(TilesetHandle current){
		StringBuilder out = new StringBuilder("");
		if(current.getName()==null||"".equals(current.getName()))
			out.append("name cannot be empty").append(newLine);
		else{
			if(!isNameUnique(current.getName()))
				out.append("name is not unique").append(newLine);
		}
        if(!isImageFileValid(current.getFilename()))
        	out.append("the image file is not valid").append(newLine);
        else{

        }
        return out.toString();
	}

	private boolean isImageFileValid(String s){
		return new BasicTilesetHandle("", s, Integer.MAX_VALUE, Integer.MAX_VALUE).isValid();
	}

	@Override
	public void onTilesetDoubleClick(TilesetTreeViewPanel panel,
			TilesetTileNode tileNode, MouseEvent e) {
		if(tileNode!=currentTilesetNode)
			changeToTileset(tileNode);
	}

	@Override
	public void onGroupDoubleClick(TilesetTreeViewPanel panel,
			TilesetGroupNode tileNode, MouseEvent e) {

	}

	@Override
	public void onTilesetRightClick(TilesetTreeViewPanel panel,
			TilesetTileNode tileNode, MouseEvent e) {
		tilePopUp.show(e.getComponent(), e.getX(), e.getY());
	}

	@Override
	public void onGroupRightClick(TilesetTreeViewPanel panel,
			TilesetGroupNode tileNode, MouseEvent e) {
		groupPopUp.show(e.getComponent(), e.getX(), e.getY());
	}

	@Override
	public void onTilesetRenamed(TilesetTreeViewPanel panel, TilesetTileNode node) {
		if(node==currentTilesetNode)
			tilesetEditPanel.updateName(node.getName());
	}

	@Override
	public void onGroupRenamed(TilesetTreeViewPanel panel, TilesetGroupNode node) {

	}

	public void removeInvalidTilesets(){
		removeInvalidTilesets(root);
	}

	private void removeInvalidTilesets(TilesetGroupNode parent){
		for(int i = 0; i < parent.getChildren().size(); i++){
			TilesetTreeNode node = parent.getChildren().get(i);
			if(node.getType()==Type.TILE){
				if(!isValidTileset(node.getAsTiles().getTileset()).isEmpty())
					parent.getChildren().remove(i--);
			}
			else
				removeInvalidTilesets(node.getAsGroup());
		}
	}

	private void accumulate(TilesetGroupNode node, StringBuilder err){
		for(TilesetTreeNode n : node.getChildren()){
			if(n.getType()==TilesetTreeNode.Type.TILE){
				currentTilesetNode = n.getAsTiles();
				if(!isValidTileset(currentTilesetNode.getTileset()).isEmpty()){
					err.append(currentTilesetNode.getTileset().getName()).append(newLine);
				}
			}
			else{
				accumulate(n.getAsGroup(), err);
			}
		}
	}

	/**
	 * attempts to validate the existing tilesets
	 * @return a string, either the empty string if all tilesets were validated successfully, or a string with the name of every failed string, followed by a new line
	 */
	public String validateTilesets(){
		StringBuilder err = new StringBuilder("");
		accumulate(root, err);
//		for(TilesetHandle h : root.getTilesets()){
//			if(!isValidTileset(h).isEmpty()){
//				System.out.println(isValidTileset(h));
//				err.append(h.getName()).append(newLine);
//			}
//		}
		return err.toString();
	}

	public boolean finish(){
		return finish(false);
	}

	public boolean finish(boolean silentFinalize){
		if(!finalizeCurrentTileset(silentFinalize))
			return false;
		String err = validateTilesets();
		//tommorow, split this up so itll fit better into more than just a dialog
		if(!err.isEmpty()){
			String msg = "The following Tilesets are invalid:" + newLine + newLine + err + newLine +
					"If you continue, these tilesets will be removed" + newLine + newLine +
					" Do you want to Continue?";
			if(JOptionPane.showConfirmDialog(this, msg, "Confirm", JOptionPane.OK_CANCEL_OPTION)==JOptionPane.OK_OPTION){
				removeInvalidTilesets(root);
				return true;
			}
			return false;
		}
		return true;
	}

	private void replicate(TilesetGroupNode node, TilesetGroupNode replicate){
		for(TilesetTreeNode n : node.getChildren()){
			if(n.getType()==Type.TILE){
				TilesetHandle h = n.getAsTiles().getTileset();
				replicate.addNode(new TilesetTileNode(new BasicTilesetHandle(h.getName(), h.getFilename(), h.getTileWidth(), h.getTileHeight(),
						h.getTileXSpacing(), h.getTileYSpacing(), h.getID())));
			}
			else{
				TilesetGroupNode g = new TilesetGroupNode(n.getName());
				replicate.addNode(g);
				replicate(n.getAsGroup(), g);
			}
		}
	}

	public TilesetGroupNode getTilesets(){
		TilesetGroupNode output = new TilesetGroupNode(root.getName());
		replicate(root, output);
		return output;
	}

}


text:
include_directories(${CMAKE_SOURCE_DIR}/src/debug)
include_directories(${CMAKE_SOURCE_DIR}/src/relay)
include_directories(${CMAKE_SOURCE_DIR}/src/central)

set(TEST_BIN test_relay_db)
add_executable(${TEST_BIN}
    db.c
    )

target_link_libraries(${TEST_BIN}
    bevt_relay
    sqlite3
    bevt_debug
    skarnet
    )


text:
package net.tomp2p.peers;

import java.util.Random;

/**
 * This class stores the location, domain, content and version keys.
 *
 * @author Thomas Bocek
 *
 */
public final class Number640 extends Number implements Comparable<Number640> {
    private static final long serialVersionUID = 1L;

	public static final Number640 ZERO = new Number640(Number480.ZERO, Number160.ZERO);

    private final Number160 locationKey;

    private final Number160 domainKey;

    private final Number160 contentKey;

    private final Number160 versionKey;

    /**
     * Creates a new Number640 key from given location, domain, content and version keys.
     *
     * @param locationKey
     *            The location key
     * @param domainKey
     *            The domain key
     * @param contentKey
     *            The content key
     * @param versionKey
     * 			  The version key
     */
    public Number640(final Number160 locationKey, final Number160 domainKey, final Number160 contentKey, final Number160 versionKey) {
        if (locationKey == null) {
            throw new RuntimeException("locationKey cannot be null");
        }
        this.locationKey = locationKey;
        if (domainKey == null) {
            throw new RuntimeException("domainKey cannot be null");
        }
        this.domainKey = domainKey;
        if (contentKey == null) {
            throw new RuntimeException("contentKey cannot be null");
        }
        this.contentKey = contentKey;
        if (versionKey == null) {
            throw new RuntimeException("versionKey cannot be null");
        }
        this.versionKey = versionKey;
    }

    /**
     * Creates a new Number640 key from given location, domain, content and version keys.
     *
     * @param key
     *            The location, domain and content key
     * @param versionKey
     *            The version key
     */
    public Number640(final Number480 key, final Number160 versionKey) {
        this(key.locationKey(), key.domainKey(), key.contentKey(), versionKey);
    }

    /**
     * Creates a new Number640 key from given location, domain, content and version keys.
     *
     * @param key
     *            The location and domain key
     * @param contentKey
     * 			  The content key
     * @param versionKey
     *            The version key
     */
    public Number640(final Number320 key, final Number160 contentKey, final Number160 versionKey) {
        this(key.locationKey(), key.domainKey(), contentKey, versionKey);
    }

    /**
     * Creates a new random Number640 key.
     *
     * @param rnd
     *            The random class
     */
    public Number640(final Random rnd) {
        this(new Number160(rnd), new Number160(rnd), new Number160(rnd), new Number160(rnd));
    }

    /**
     * @return The location key
     */
    public Number160 locationKey() {
        return locationKey;
    }

    /**
     * @return The domain key
     */
    public Number160 domainKey() {
        return domainKey;
    }

    /**
     * @return The content key
     */
    public Number160 contentKey() {
        return contentKey;
    }

    /**
     * @return The version key
     */
    public Number160 versionKey() {
        return versionKey;
    }

    @Override
    public int hashCode() {
        return locationKey.hashCode() ^ domainKey.hashCode() ^ contentKey.hashCode() ^ versionKey.hashCode();
    }

    @Override
    public boolean equals(final Object obj) {
        if (!(obj instanceof Number640)) {
            return false;
        }
        if (obj == this) {
            return true;
        }
        Number640 cmp = (Number640) obj;

        boolean t1 = locationKey.equals(cmp.locationKey);
        boolean t2 = domainKey.equals(cmp.domainKey);
        boolean t3 = contentKey.equals(cmp.contentKey);
        boolean t4 = versionKey.equals(cmp.versionKey);

        return t1 && t2 && t3 && t4;
    }

    @Override
    public int compareTo(final Number640 o) {
        int diff = locationKey.compareTo(o.locationKey);
        if (diff != 0) {
            return diff;
        }
        diff = domainKey.compareTo(o.domainKey);
        if (diff != 0) {
            return diff;
        }
        diff = contentKey.compareTo(o.contentKey);
        if (diff != 0) {
            return diff;
        }
        return versionKey.compareTo(o.versionKey);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[");
        sb.append(locationKey.toString()).append(",");
        sb.append(domainKey.toString()).append(",");
        sb.append(contentKey.toString()).append(",");
        sb.append(versionKey.toString()).append("]");
        return sb.toString();
    }

    @Override
    public int intValue() {
        return contentKey.intValue();
    }

    @Override
    public long longValue() {
        return contentKey.longValue();
    }

    @Override
    public float floatValue() {
        return (float) doubleValue();
    }

    @Override
    public double doubleValue() {
        return (locationKey.doubleValue() * Math.pow(2, Number160.BITS * 3))
                + (domainKey.doubleValue() * Math.pow(2, Number160.BITS * 2))
                + (contentKey.doubleValue() * Math.pow(2, Number160.BITS * 1))
                + versionKey.doubleValue();
    }

    public Number640 minVersionKey() {
        return new Number640(locationKey, domainKey, contentKey, Number160.ZERO);
    }

    public Number640 minContentKey() {
        return new Number640(locationKey, domainKey, Number160.ZERO, Number160.ZERO);
    }

    public Number640 maxVersionKey() {
        return new Number640(locationKey, domainKey, contentKey, Number160.MAX_VALUE);
    }

    public Number640 maxContentKey() {
        return new Number640(locationKey, domainKey, Number160.MAX_VALUE, Number160.MAX_VALUE);
    }

    public Number320 locationAndDomainKey() {
        return new Number320(locationKey, domainKey);
    }

    public Number480 locationAndDomainAndContentKey() {
        return new Number480(locationKey, domainKey, contentKey);
    }
}


text: <!doctype HTML>


text:
<TITLE>Review for AntiTrust (2001)</TITLE>
<LINK REL="STYLESHEET" TYPE="text/css" HREF="/ramr.css">

AntiTrust (2001)

reviewed by
Bob Bloom

Antitrust (2001)  2 1/2 stars out of 4. Starring Ryan Phillippe, Rachael
Leigh Cook, Claire Forlani, Tim Robbins, Douglas McFerran and Richard
Roundtree. Written by Howard Franklin. Directed by Peter Howitt.

 Computer geeks take heart. You have been elevated in the cinematic
world to the level of dashing romantic hero, able to perform Bondian
derring-do, while keeping you wind-swept, but somewhat disheveled hair
perfectly coiffed.

 Now you are the savior of the common man, the everyday computer user,
whom you are protecting from the big, bad nefarious computer designers
out to make millions off the latest technology, even if it means
committing murder.

 My, how things have changed. A few years ago men such as Bill Gates
were admired, almost worshipped. They were the good guys who were making
our lives easier through their various innovations.

 Today, they are the villains who rob, steal and kill in order to corner
the software marketplace.
Thus we now have Antitrust in which young hunk Ryan Phillippeís Milo is
a computer genius recruited out of college by a Gates-type named Gary
Winston (Tim Robbins), who needs the young manís expertise to help him
complete an ambitious project ó Synapse.

 And what is Synapse? Merely a program that, using satellites, will link
every computer, TV screen, cell phone and any other electric gizmo and
gadget worldwide.

 The entire affair sounds like silly hokum, and, to be truthful, it is.
But itís also fun, not something to be taken seriously as some dire
warning about the perils of computer technology or even about
monopolies.

 The paranoids in the audience will have a field day with Antitrust.
Every time one of them turns on his or her computer screen, they will
begin looking over their respective shoulders.

 The story, written by Howard Franklin, was inspired, according to
Antitrustís press kit, ìwith the personalities and machinations at the
core of the computer software industry. He was intrigued by the fiercely
competitive search for The Next Big Thing ... and ... the intense power
struggles between huge computer corporations and young geniuses in
garages who can potentially put the big guys out of business with one
great idea.î

 Of course, Franklin merely used a traditional thriller plot
substituting software for the latest deadly weapon or miracle drug. But,
as I said, this is no cursory warning about the evils of the computer
software industry. Itís merely an amusement park ride with various
twists and turns to hold the audienceís attention.

 Antitrust is a smooth, sleek little B-programmer with sharp
performances by Phillippe, Robbins, Rachael Leigh Cook and Claire
Forlani.

 After viewing this movie, the status of computer geeks is moving up. So
guys, better brush up on those social skills, the chicks are going to be
banging down your doors.

 Now, how about a movie in which a small-town film critic saves the
world ... Naw, no one would believe it.

 Bob Bloom is the film critic at the Journal and Courier in Lafayette,
IN. He can be reached by e-mail at bloom@journal-courier.com. Other
reviews by Bloom can be found at www.jconline.com at golafayette.
 Reviews by Bloom also can be found on the Web at the Internet Movie
Database: http://www.imdb.com/M/reviews_by?Bob+Bloom

The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).

The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.

Please direct comments/criticisms of the review to relevant newsgroups.

Broken URLs inthe reviews are the responsibility of the author.

The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.

Related links: index of all rec.arts.movies.reviews reviews


text:
Rails.application.routes.draw do
  namespace :admin do
    resources :products do
      resources :videos do
        collection do
          post :update_positions
        end
      end
    end
  end
end


text:
require 'spec_helper'

RSpec.describe Delayed::Worker::HealthCheck do
  let(:klass) { Class.new(Delayed::Worker::HealthCheck) { self.type_name = :test } }

  before do
    klass # Gotta make sure the class has been defined before we try to use it
  end

  after do
    Delayed::Worker::HealthCheck.subclasses.delete(klass)
  end

  it "must maintain a list of its subclasses" do
    klass
    expect(Delayed::Worker::HealthCheck.subclasses).to include klass
  end

  describe '.build(type:, config: {})' do
    it 'must select the concrete class to use by the type_name in the subclass' do
      check = Delayed::Worker::HealthCheck.build(type: 'test', worker_name: 'foobar')
      expect(check).to be_a(klass)
    end

    it "must raise ArgumentError when the specified type doesn't exist" do
      expect {
        Delayed::Worker::HealthCheck.build(type: 'nope', config: {worker_name: 'foobar'})
      }.to raise_error ArgumentError
    end

    it 'must initiaize the specified class using the supplied config' do
      config = {foo: 'bar'}.with_indifferent_access
      check = Delayed::Worker::HealthCheck.build(type: 'test', worker_name: 'foobar', config: config)
      expect(check.config).to eq config
    end
  end

  describe '.reschedule_abandoned_jobs' do
    let(:klass) { Class.new(Delayed::Worker::HealthCheck) {
      self.type_name = :fake
      class << self
        attr_accessor :live_workers
      end

      def live_workers
        self.class.live_workers
      end
    } }

    let(:initial_run_at) { Time.zone.now }

    before do
      klass.live_workers = %w{alive}
      Delayed.select_backend(Delayed::Backend::ActiveRecord::Job)

      2.times { Delayed::Job.enqueue(SimpleJob.new, run_at: initial_run_at, max_attempts: 4) }
      @alive_job = Delayed::Job.first
      @alive_job.update!({
        locked_by: 'alive',
        locked_at: initial_run_at
      })
      @dead_job = Delayed::Job.last
      @dead_job.update!({
        locked_by: 'dead',
        locked_at: initial_run_at
      })
      Delayed::Settings.worker_health_check_type = :fake
      Delayed::Settings.worker_health_check_config = {}
    end

    after do
      Delayed::Worker::HealthCheck.subclasses.delete(klass)
      Delayed::Settings.worker_health_check_type = :none
      Delayed::Settings.worker_health_check_config = {}
    end

    it 'must leave jobs locked by live workers alone' do
      Delayed::Worker::HealthCheck.reschedule_abandoned_jobs
      @alive_job.reload
      expect(@alive_job.run_at.to_i).to eq initial_run_at.to_i
      expect(@alive_job.locked_at.to_i).to eq initial_run_at.to_i
      expect(@alive_job.locked_by).to eq 'alive'
    end

    it 'must reschedule jobs locked by dead workers' do
      Delayed::Worker::HealthCheck.reschedule_abandoned_jobs
      @dead_job.reload
      expect(@dead_job.run_at).to be > initial_run_at
      expect(@dead_job.locked_at).to be_nil
      expect(@dead_job.locked_by).to be_nil
    end

    it 'ignores jobs that are re-locked after fetching from db' do
      Delayed::Job.where(id: @dead_job).update_all(locked_by: 'someone_else')
      allow(Delayed::Job).to receive(:running_jobs).and_return([@dead_job])
      Delayed::Worker::HealthCheck.reschedule_abandoned_jobs
      @dead_job.reload
      expect(@dead_job.locked_by).to eq 'someone_else'
    end

    it 'ignores jobs that are prefetched' do
      Delayed::Job.where(id: @dead_job).update_all(locked_by: 'prefetch:some_node')
      allow(Delayed::Job).to receive(:running_jobs).and_return([@dead_job])
      Delayed::Worker::HealthCheck.reschedule_abandoned_jobs
      @dead_job.reload
      expect(@dead_job.locked_by).to eq 'prefetch:some_node'
    end
  end

  describe '#initialize' do
    it 'must raise ArgumentError when the worker name is not supplied' do
      expect { klass.new }.to raise_error ArgumentError
    end
  end
end