text:
/*global jQuery, fluid, cspace*/

(function ($, fluid) {

    "use strict";

    fluid.log("Autocomplete.js loaded");

    // An autocomplete component that is used for term completion
    // in Collection Space.
    fluid.defaults("cspace.autocomplete", {
        gradeNames: ["fluid.viewComponent", "autoInit"],
        // Minimum number of character to activate the term completion.
        minChars: 3,
        model: {
            authorities: [],
            matches: []
        },
        // Delay before making a request to complete the term.
        delay: 500,
        invokers: {
            // Invoker that positions buttons etc.
            buttonAdjustor: {
                funcName: "cspace.autocomplete.buttonAdjustor",
                args: ["{autocomplete}.closeButton", "{autocomplete}.model", "{arguments}.0"]
            },
            // Invoker that is used when authority is selected.
            selectAuthority: {
                funcName: "cspace.autocomplete.selectAuthority",
                args: ["{autocomplete}", "{arguments}.0"]
            },
            // Invoker that reverts the current state of the autocomplete
            // widget to its original.
            revertState: {
                funcName: "cspace.autocomplete.revertState",
                args: ["{autocomplete}"]
            },
            // Invoker, used when matched term is selected.
            selectMatch: {
                funcName: "cspace.autocomplete.selectMatch",
                args: ["{autocomplete}", "{arguments}.0"]
            },
            // Invoker used to display error message via messageBar.
            displayErrorMessage: "cspace.util.displayErrorMessage"
        },
        components: {
            vocab: "{vocab}",
            // Autocomplete view subcomponents - autocomplete's actual UI.
            autocomplete: {
                type: "fluid.autocomplete.autocompleteView",
                options: {
                    minChars: "{cspace.autocomplete}.options.minChars",
                    delay: "{cspace.autocomplete}.options.delay"
                }
            },
            // Common even container.
            eventHolder: {
                type: "fluid.autocomplete.eventHolder",
                priority: "first"
            },
            // A popup widget subcomponent.
            popup: {
                type: "cspace.autocomplete.popup",
                options: {
                    model: "{autocomplete}.model",
                    applier: "{autocomplete}.applier",
                    inputField: "{autocomplete}.autocompleteInput",
                    elPaths: "{autocomplete}.options.elPaths"
                }
            },
            // Data source to get all available authorities for the
            // autocomplete.
            authoritiesSource: {
                type: "cspace.autocomplete.authoritiesDataSource"
            },
            // Data source to query for matches.
            matchesSource: {
                type: "cspace.autocomplete.matchesDataSource"
            },
            // Data source to create a new term.
            newTermSource: {
                type: "cspace.autocomplete.newTermDataSource"
            },
            // Close button subcomponent.
            closeButton: {
                type: "cspace.autocomplete.closeButton"
            }
        },
        urls: {
            vocab: "&vocab=%vocab",
            vocabSingle: "?vocab=%vocab"
        },
        parentBundle: "{globalBundle}",
        elPaths: {
            preferred: "preferred",
            displayName: "displayName",
            urn: "urn",
            baseUrn: "baseUrn",
            displayNames: "displayNames",
            matches: "matches",
            type: "type",
            csid: "csid",
            rowDisabled: "disabled",
            namespace: "namespace"
        },
        preInitFunction: "cspace.autocomplete.preInit",
        postInitFunction: "cspace.autocomplete.postInit",
        finalInitFunction: "cspace.autocomplete.finalInit"
    });

    fluid.demands("authoritiesSource", ["cspace.hierarchyAutocomplete", "cspace.autocomplete", "cspace.nonAuthority"], {
        funcName: "cspace.autocomplete.structuredObjectsAuthoritiesSource",
        options: {
            recordType: "{cspace.recordEditor}.options.recordType"
        }
    });

    // Data source used when autocomplete is used within the context of
    // structured objects (cataloging at the memomet but can be used anywhere).
    fluid.defaults("cspace.autocomplete.structuredObjectsAuthoritiesSource", {
        gradeNames: ["fluid.littleComponent", "autoInit"],
        finalInitFunction: "cspace.autocomplete.structuredObjectsAuthoritiesSource.finalInit",
        permission: "create",
        components: {
            permissionsResolver: "{permissionsResolver}",
            recordTypeManager: "{recordTypeManager}",
            globalBundle: "{globalBundle}"
        }
    });

    cspace.autocomplete.structuredObjectsAuthoritiesSource.finalInit = function (that) {
        that.resolveUrl = function () {return "";};
        that.get = function (directModel, callback) {
            var permitted = cspace.permissions.getPermissibleRelatedRecords(that.options.recordType, that.permissionsResolver, that.recordTypeManager, that.options.permission),
                togo = [];
            fluid.each(permitted, function (recordType) {
                togo.push({
                    type: recordType,
                    fullName: that.globalBundle.resolve("hierarchy-createNew")
                });
                togo.push({
                    type: recordType,
                    fullName: that.globalBundle.resolve("hierarchy-createFromExisting"),
                    createFromExisting: true
                });
            });
            callback(togo);
        };
    };

    // Expand urls based on vocab info.
    cspace.autocomplete.preInit = function (that) {
        fluid.each(["vocab", "vocabSingle"], function (url) {
            var urls = that.options.urls;
            if (!that.model.vocab) {
                urls[url] = "";
                return;
            }
            urls[url] = fluid.stringTemplate(urls[url], {
                vocab: that.model.vocab
            });
        });
    };

    cspace.autocomplete.postInit = function (that) {
        // Hide actual input field bound to a model.
        that.hiddenInput = that.container.is("input") ? that.container : $("input", that.container.parent());
        that.hiddenInput.hide();
        that.parent = that.hiddenInput.parent();

        // Create an input that will be used by autocomplete.
        var autocompleteInput = $("<input/>");
        autocompleteInput.insertAfter(that.hiddenInput);
        that.autocompleteInput = autocompleteInput;

        // Create a coantiner for a popup.
        var popup = $("

");
        var topRelative = findTopRelative(autocompleteInput[0]);
        topRelative.append(popup);
        // neither of these two options work for layout - input sibling fails on with, body never appears at all
        //popup.insertAfter(autocompleteInput);
        //$("body").append(popup);
        that.popupElement = popup;

        var initialRec = cspace.autocomplete.urnToRecord(that.hiddenInput.val());

        updateAuthoritatively(that, initialRec);
    };

    cspace.autocomplete.finalInit = function (that) {
        var authUrl;
        that.resolveMessage = that.options.parentBundle.resolve;
        that.closeButton.button.attr("title", that.resolveMessage("autocomplete-closeButton"));
        // Add a listener to the onSearch event.
        that.autocomplete.events.onSearch.addListener(function (newValue, permitted) {
            that.applier.requestChange("term", newValue);
            if (permitted) {
                that.buttonAdjustor(true); // hide the button to show the "loading indicator"
                var matchesUrl = that.matchesSource.resolveUrl(that.model);
                // Fetch matches if available.
                that.matchesSource.get(that.model, function (matches) {
                    if (!matches) {
                        that.displayErrorMessage(fluid.stringTemplate(that.resolveMessage("emptyResponse"), {
                            url: matchesUrl
                        }));
                        return;
                    }
                    if (matches.isError === true) {
                        fluid.each(matches.messages, function (message) {
                            that.displayErrorMessage(message);
                        });
                        return;
                    }
                    that.applier.requestChange("matches", matches);
                    // Adjust buttons and show popup.
                    that.buttonAdjustor();
                    that.popup.open();
                    that.autocomplete.events.onSearchDone.fire(newValue);
                }, cspace.util.provideErrorCallback(that, matchesUrl, "errorFetching"));
            }
            else {
                // If invalid term, revert.
                if (newValue === "") { // CSPACE-1651
                    var blankRec = cspace.autocomplete.urnToRecord("");
                    updateAuthoritatively(that, blankRec);
                }
                that.buttonAdjustor();
                that.popup.closeWithFocus();
            }
        });

        // Bind several events to appropriate autocomplete's invokers.
        that.eventHolder.events.selectMatch.addListener(that.selectMatch);
        that.eventHolder.events.selectAuthority.addListener(that.selectAuthority);
        that.eventHolder.events.revertState.addListener(that.revertState);

        // TODO: risk of asynchrony
        authUrl = that.authoritiesSource.resolveUrl();
        that.authoritiesSource.get(null, function (authorities) {
            // After autocomplete authorities (configuration) is fetched,
            // do the rest of the setup. Handler permissions, sort authorities
            // based on vocab.
            if (!authorities) {
                that.displayErrorMessage(fluid.stringTemplate(that.resolveMessage("emptyResponse"), {
                    url: authUrl
                }));
                return;
            }
            if (authorities.isError === true) {
                fluid.each(authorities.messages, function (message) {
                    that.displayErrorMessage(message);
                });
                return;
            }
            that.applier.requestChange("authorities", authorities);
            if (that.handlePermissions) {
                that.handlePermissions();
            }
            that.model.authorities.sort(function (auth1, auth2) {
                return cspace.autocomplete.compareAuthorities(that.vocab, auth1, auth2);
            });
        }, cspace.util.provideErrorCallback(that, authUrl, "errorFetching"));

        // If closed revert state.
        that.closeButton.button.click(function () {
            that.eventHolder.events.revertState.fire();
            return false;
        });
    };

    // Sorting algo for authorities and their vocabularies.
    cspace.autocomplete.compareAuthorities = function (vocab, auth1, auth2) {
        var vocabType1 = auth1.type.split("-"),
            vocabType2 = auth2.type.split("-"),
            type1 = vocabType1[0],
            type2 = vocabType2[0],
            vocab1 = vocabType1[1],
            vocab2 = vocabType2[1],
            order;
        if (type1 !== type2) {
            return 0;
        }
        if (!vocab.hasVocabs(type1)) {
            return 0;
        }
        order = vocab.authority[type1].order.vocabs;
        return order.indexOf(vocab1) - order.indexOf(vocab2);
    };

    // Basic event holder component.
    fluid.defaults("fluid.autocomplete.eventHolder", {
        gradeNames: ["fluid.eventedComponent", "autoInit"],
        events: {
            revertState: null,
            selectAuthority: null,
            afterSelectAuthority: null,
            selectMatch: null,
            afterSelectMatch: null
        }
    });

    // TODO: temporary conversion function whilst we ensure that all records are transmitted faithfully
    // from application layer with a reliable encoding (probably JSON itself)
    cspace.autocomplete.urnToRecord = function (string) {
        if (!string) {
            return {
                urn: "",
                displayName: ""
            };
        }
        else if (string.substring(0, 4) === "urn:") {
            return {
                urn: string,
                displayName: cspace.util.urnToString(string)
            };
        }
        else {
            return {
                urn: "urn:error:in:application:layer:every:autocomplete:field:must:have:an:urn",
                displayName: string
            };
        }
    };

    // Inspiration from http://stackoverflow.com/questions/158070/jquery-how-to-position-one-element-relative-to-another
    cspace.internalPositioner = function (jTarget, jToPosition, adjustX, adjustY) {
        var pos = jTarget.position();
        var target = fluid.unwrap(jTarget);
        var toPosition = fluid.unwrap(jToPosition);
        var left = pos.left + target.offsetWidth - toPosition.offsetWidth + adjustX;
        var top = pos.top + (target.offsetHeight - toPosition.offsetHeight) / 2 + adjustY;
        jToPosition.css({
            position: "absolute",
            zIndex: 5000,
            left: left + "px",
            top: top + "px"
        });
    };

    /** A vestigial "autocomplete component" which does nothing other than track keystrokes
     * and fire events. It also deals with styling of a progress indicator attached to the
     * managed element, probably an <input>. */

    fluid.defaults("fluid.autocomplete.autocompleteView", {
        gradeNames: ["fluid.viewComponent"],
        events: {
            onSearch: null,
            onSearchDone: null
        },
        styles: {
            baseStyle: "cs-autocomplete-input",
            loadingStyle: "cs-autocomplete-loading"
        },
        components: {
            eventHolder: "{eventHolder}"
        }
    });

    fluid.autocomplete.bindListener = function (that) {
        that.container.keydown(function () {
            clearTimeout(that.outFirer);
            that.outFirer = setTimeout(that.search, that.options.delay);
        });
        that.container.change(function () {
            that.oldValue = that.container.val();
        });
    };

    fluid.autocomplete.autocompleteView = function (container, options) {
        var that = fluid.initView("fluid.autocomplete.autocompleteView", container, options);
        fluid.initDependents(that);
        that.container.addClass(that.options.styles.baseStyle);

        fluid.autocomplete.bindListener(that);

        // ====== Bind some of the autocomplete events and their listeners.
        that.events.onSearch.addListener(function (term, permitted) {
            if (permitted) {
                container.addClass(that.options.styles.loadingStyle);
            }
        });

        that.events.onSearchDone.addListener(function () {
            container.removeClass(that.options.styles.loadingStyle);
        });

        that.events.onSearchDone.addListener(function () {
            delete that.searching;
            if (that.newValue) {
                that.search(that.newValue);
            }
        }, undefined, undefined, "last");

        fluid.each(["selectAuthority", "selectMatch"], function (event) {
            that.eventHolder.events[event].addListener(function () {
                container.addClass(that.options.styles.loadingStyle);
            });
        });
        fluid.each(["afterSelectMatch", "afterSelectAuthority"], function (event) {
            that.eventHolder.events[event].addListener(function () {
                container.removeClass(that.options.styles.loadingStyle);
            });
        });
        // ================================================================

        // Handler search, taking care of timeouts based on delay and user
        // input.
        that.search = function (newValue) {
            var permitted;
            newValue = newValue || that.container.val();
            permitted = newValue.length >= that.options.minChars;

            if (newValue === that.oldValue) {
                return;
            }

            if (permitted) {
                if (that.searching) {
                    that.newValue = newValue;
                    return;
                }
                that.searching = true;
                that.oldValue = newValue;
                if (that.newValue) {
                    delete that.newValue;
                }
            } else {
                delete that.newValue;
                delete that.searching;
            }

            that.events.onSearch.fire(newValue, permitted);
        };

        that.suppress = function () {
            clearTimeout(that.outFirer);
            that.outFirer = null;
            that.oldValue = that.container.val();
        };
        that.suppress();

        return that;
    };

    /**** Definitions for testing environment - TODO: move to separate file somewhere ****/
    fluid.defaults("cspace.autocomplete.testAuthoritiesDataSource", {
        url: "%test/data/autocomplete/authorities.json"
    });

    cspace.autocomplete.testAuthoritiesDataSource = cspace.URLDataSource;

    cspace.autocomplete.testMatchesParser = function (data, directModel) {
        var togo = [];
        var lowterm = directModel.term.toLowerCase();
        fluid.each(data, function (item) {
            if (fluid.find(item.displayNames, function (displayName) {
                if (displayName.toLowerCase().indexOf(lowterm) !== -1) {
                    return displayName;
                }
            })) {
                togo.push(item);
            }
        });
        return togo;
    };

    fluid.defaults("cspace.autocomplete.testMatchesDataSource", {
        url: "%test/data/autocomplete/matches.json",
        responseParser: cspace.autocomplete.testMatchesParser,
        delay: 1
    });

    cspace.autocomplete.testMatchesDataSource = cspace.URLDataSource;

    cspace.autocomplete.testNewTermDataSource = function () {
        var url = "%tenant/%tname/%termUrl";
        return {
            options: {
                url: url
            },
            resolveUrl: function () {
                var expander = fluid.invoke("cspace.urlExpander");
                var replaced = url;
                replaced = expander(replaced);
                return replaced;
            },
            set: function (model, directModel, callback) {
                fluid.log("Post of new term record " + JSON.stringify(model) + " to URL " + directModel.termURL);
                callback({urn: "urn:" + fluid.allocateGuid(), displayName: model.fields.displayName});
            }
        };
    };
    /**** End testing definitions ****/

    // Basic close button component that takes care of its positioning
    // and appropriate events.
    fluid.defaults("cspace.autocomplete.closeButton", {
        gradeNames: ["fluid.viewComponent"],
        styles: {
            button: "cs-autocomplete-closebutton"
        },
        markup: "",
        positionAdjustment: {
            x: -1,
            y: 0
        }
    });

    cspace.autocomplete.closeButton = function (container, options) {
        var that = fluid.initView("cspace.autocomplete.closeButton", container, options);
        var button = $(that.options.markup);
        button.addClass(that.options.styles.button);
        button.insertAfter(that.container);
        //$("body").append(button);
        button.hide();
        that.show = function () {
            button.show();
            cspace.internalPositioner(that.container, button, that.options.positionAdjustment.x, that.options.positionAdjustment.y);
        };
        that.hide = function () {
            button.hide();
        };
        that.button = button;
        return that;
    };

    var buildValueBinding = function (fieldName) {
        return "${" + fluid.model.composeSegments("{row}", fieldName) + "}";
    };

    // Build part of the autocomplete's popup tree that represents,
    // authoity selection for a new term.
    cspace.autocomplete.makeAuthoritySelectionTree = function (tree, repeatID, listPath, fieldName) {
        tree.expander = fluid.makeArray(tree.expander);
        tree.expander.push({
            repeatID: repeatID,
            type: "fluid.renderer.repeat",
            pathAs: "row",
            controlledBy: listPath,
            tree: buildValueBinding(fieldName)
        });
    };

    // Build part of the tree responsible for rendering Preferred -
    // Non-Preferred authority names.
    cspace.autocomplete.makePNPSelectionTree = function (elPaths, styles, tree, repeatID) {
        var preferred = elPaths.preferred,
            displayName = elPaths.displayName,
            rowDisabled = elPaths.rowDisabled;

        tree.expander = fluid.makeArray(tree.expander);

        tree.expander.push({
            repeatID: repeatID,
            type: "fluid.renderer.repeat",
            pathAs: "row",
            valueAs: "rowValue",
            controlledBy: "matches",
            tree: {
                expander: [{
                    type: "fluid.renderer.condition",
                    condition: buildValueBinding(preferred),
                    trueTree: {
                        matchItemContent: {
                            value: buildValueBinding(displayName)
                        }
                    },
                    falseTree: {
                        expander: [{
                            type: "fluid.renderer.condition",
                            condition: buildValueBinding(rowDisabled),
                            trueTree: {
                                matchItemContent: {
                                    value: buildValueBinding(displayName),
                                    decorators: {
                                        type: "addClass",
                                        classes: styles.nonPreferredDisabled
                                    }
                                }
                            },
                            falseTree: {
                                matchItemContent: {
                                    value: buildValueBinding(displayName),
                                    decorators: {
                                        type: "addClass",
                                        classes: styles.nonPreferred
                                    }
                                }
                            }
                        }]
                    }
                }]
            }
        });
    };

    // Generic authocomplete popup produceTree function.
    cspace.autocomplete.produceTree = function (that) {
        var tree = {},
            model = that.model;

        var stopCharPattern = /[\^,\*]$/,
            startCharPattern = /^[\^,\*]/,
            interstitialWildcard = /\*/;

        if (stopCharPattern.test(model.term) || startCharPattern.test(model.term)) {
            model.term = model.term.replace(stopCharPattern, "").replace(startCharPattern, "");
        }

        if (model.authorities.length > 0 && !(interstitialWildcard.test(model.term))) {
            tree.addToPanel = {};
            tree.addTermTo = {
                messagekey: "autocomplete-addTermTo",
                args: ["${term}"]
            };
            cspace.autocomplete.makeAuthoritySelectionTree(tree, "authorityItem", "authorities", "fullName");
        }
        if (model.matches.length < 1) {
            tree.noMatches = {
                messagekey: "autocomplete-noMatches"
            };
        }
        else {
            tree.matches = {};
            cspace.autocomplete.makePNPSelectionTree(that.options.elPaths, that.options.styles, tree, "matchItem");
        }
        return tree;
    };

    // Creator function for popup subcomponent.
    cspace.autocomplete.popup = function (container, options) {
        var that = fluid.initRendererComponent("cspace.autocomplete.popup", container, options);
        fluid.initDependents(that);
        that.union = $(container).add(fluid.unwrap(that.options.inputField));

        var decodeItem = function (item) { // TODO: make a generic utility for this (integrate with ViewParameters for URLs)
            var togo = {
                EL: that.renderer.boundPathForNode(item)
            };
            togo.parsed = fluid.model.parseEL(togo.EL);
            if (togo.parsed.length === 3) {
                togo.type = togo.parsed[0];
                togo.index = togo.parsed[1];
            }
            return togo;
        };

        that.activateFunction = function (item) {
            var decoded = decodeItem(item.target);
            if (decoded.type) {
                that.eventHolder.events[decoded.type === "authorities" ? "selectAuthority" : "selectMatch"].fire(decoded.index);
            }
        };
        that.container.click(that.activateFunction);

        that.close = function () {
            that.container.dialog("close");
            that.container.html("");
        };

        that.closeWithFocus = function () {
            that.close();
            that.options.inputField.focus();
        };

        that.blurHandler = fluid.deadMansBlur(that.union, {
            exclusions: {union: that.union},
                handler: function () {
                that.eventHolder.events.revertState.fire();
            }
        });

        // Handle keyboard selection and activation.
        function makeHighlighter(funcName) {
            return function (item) {
                var decoded = decodeItem(item);
                if (decoded.type) {
                    $(item)[funcName](that.options.styles[decoded.type + "Select"]);
                }
            };
        }
        that.selectableContainer = that.container.parent();
        // TODO: sloppy use of "parent" here is necessary to prevent removal of tabindex order
        that.selectable = fluid.selectable(that.selectableContainer, {
            selectableElements: that.options.inputField,
            noBubbleListeners: true,
            onSelect: makeHighlighter("addClass"),
            onUnselect: makeHighlighter("removeClass"),
            selectablesTabindex: ""
        });

        that.escapeHandler = function (event) { // TODO: too annoying to use plugin because of FLUID-1313
            if (event.keyCode === $.ui.keyCode.ESCAPE) {
                that.eventHolder.events.revertState.fire();
            }
        };
        // We trigger only on KEYUP since at least Firefox has a totally unpreventable
        // default effect in between keypress and keyup of returning the field to its
        // old value.
        that.union.keyup(that.escapeHandler);

        that.eventHolder.events.afterSelectAuthority.addListener(that.closeWithFocus);
        that.eventHolder.events.afterSelectMatch.addListener(that.closeWithFocus);
        return that;
    };

    cspace.autocomplete.popup.preInit = function (that) {
        // Process the popup model before rendering.
        cspace.util.preInitMergeListeners(that.options, {
            prepareModelForRender: function (model, applier, that) {
                var matches = [],
                    preferred = that.options.elPaths.preferred,
                    displayName = that.options.elPaths.displayName,
                    displayNames = that.options.elPaths.displayNames,
                    urn = that.options.elPaths.urn,
                    baseUrn = that.options.elPaths.baseUrn,
                    csid = that.options.elPaths.csid,
                    type = that.options.elPaths.type,
                    rowDisabled = that.options.elPaths.rowDisabled,
                    matchesPath = that.options.elPaths.matches,
                    namespace = that.options.elPaths.namespace;
                fluid.each(fluid.get(model, matchesPath), function (match) {
                    var recordCSID = fluid.get(that.options, "recordModel.csid");
                    if (recordCSID && recordCSID === match[csid]) {
                        return;
                    }
                    var vocab = cspace.vocab.resolve({
                        recordType: match.type,
                        model: match,
                        vocab: that.vocab
                    }), displayNameList = fluid.get(match, displayNames), disabled = false;

                    if (!that.vocab.isNptAllowed(vocab, match.type)) {
                        disabled = true;
                    }

                    // Builde "matches" structure with all data, necessary for rendering.
                    matches = matches.concat(fluid.transform(displayNameList, function (thisDisplayName, index) {
                        var elem = {};
                        elem[urn] = match[baseUrn].concat("'", thisDisplayName, "'");
                        elem[displayName] = thisDisplayName;
                        elem[preferred] = index === 0;
                        elem[type] = match.type;
                        elem[csid] = match.csid;
                        elem[rowDisabled] = (!elem[preferred] && (disabled === true));
                        elem[namespace] = match.namespace;
                        return elem;
                    }));
                });
                that.applier.requestChange("matches", matches);
            }
        });
    };

    // Produce tree function specific to structured objects.
    cspace.autocomplete.produceTreeStructuredObjects = function (that) {
        var tree = cspace.autocomplete.produceTree(that);
        fluid.merge({
            addTermTo: "replace"
        }, tree, {
            addTermTo: {},
            newTermNamePrefix: {
                messagekey: "autocomplete-newTermNamePrefix"
            },
            newTermName: {
                value: "${term}"
            },
            newTermNamePostfix: {
                messagekey: "autocomplete-newTermNamePostfix"
            }
        });
        return tree;
    };

    /* miniView component */
    fluid.defaults("cspace.autocomplete.popup.miniView", {
        gradeNames: ["fluid.viewComponent", "autoInit"],
        events: {
            onModel: null,
            onHide: null,
            onShow: null,
            onContext: null,
            onRender: null,
            onReady: null
        },
        listeners: {
            onContext: "{that}.onContext",
            onModel: "{that}.onModel",
            onHide: "{that}.hide",
            onShow: "{that}.show",
            onReady: "{that}.onReady"
        },
        components: {
            // Holds context of which recordType is hilighted.
            context: {
                type: "fluid.typeFount",
                options: {
                    targetTypeName: "{cspace.autocomplete.popup.miniView}.options.context"
                },
                createOnEvent: "onContext"
            },
            // Data source to fetch the data to be rendered in miniview.
            dataSource: {
                type: "cspace.autocomplete.popup.miniView.dataSource",
                createOnEvent: "onContext"
            },
            // OVerridable component that extracts correct CSID based on record
            // type, vocab.
            urnToCSID: {
                type: "cspace.autocomplete.popup.miniView.urnToCSID",
                createOnEvent: "onContext"
            },
            // Actual component that does the rendering.
            renderer: {
                container: "{cspace.autocomplete.popup.miniView}.container",
                type: "cspace.autocomplete.popup.miniView.renderer",
                createOnEvent: "onRender",
                options: {
                    model: "{cspace.autocomplete.popup.miniView}.model.basic",
                    recordType: "{cspace.autocomplete.popup.miniView}.model.attributes.type",
                    vocab: "{cspace.autocomplete.popup.miniView}.model.attributes.namespace",
                    urn: "{cspace.autocomplete.popup.miniView}.model.attributes.urn"
                }
            }
        },
        // Delay to display the miniView.
        delay: 1000,
        showTimer: undefined,
        model: null,
        preInitFunction: "cspace.autocomplete.popup.miniView.preInit"
    });

    // Component that handles correct CSID extraction from the urn.
    fluid.defaults("cspace.autocomplete.popup.miniView.urnToCSID", {
        gradeNames: ["autoInit", "fluid.littleComponent"],
        preInitFunction: "cspace.autocomplete.popup.miniView.urnToCSID.preInit"
    });

    cspace.autocomplete.popup.miniView.urnToCSID.preInit = function (that) {
        that.convert = function (urn) {
            fluid.invokeGlobalFunction(that.options.toCSID, [urn]);
        };
    };

    // Mini view renderer comopnent.
    fluid.defaults("cspace.autocomplete.popup.miniView.renderer", {
        gradeNames: ["fluid.rendererComponent", "autoInit"],
        resources: {
            template: {
                expander: {
                    type: "fluid.deferredInvokeCall",
                    func: "cspace.specBuilder",
                    args: {
                        forceCache: true,
                        fetchClass: "slowTemplate",
                        url: "%webapp/html/components/MiniViewTemplate.html"
                    }
                }
            }
        },
        renderOnInit: true,
        parentBundle: "{globalBundle}",
        strings: {},
        listeners: {
            prepareModelForRender: "{that}.prepareModelForRender"
        },
        selectors: {
            displayName: ".csc-autocomplete-popup-miniView-displayName",
            field1: ".csc-autocomplete-popup-miniView-field1",
            field2: ".csc-autocomplete-popup-miniView-field2",
            field3: ".csc-autocomplete-popup-miniView-field3",
            field4: ".csc-autocomplete-popup-miniView-field4",
            field1Label: ".csc-autocomplete-popup-miniView-field1Label",
            field2Label: ".csc-autocomplete-popup-miniView-field2Label",
            field3Label: ".csc-autocomplete-popup-miniView-field3Label",
            field4Label: ".csc-autocomplete-popup-miniView-field4Label"
        },
        url: cspace.componentUrlBuilder("%webapp/html/%recordType.html?csid=%csid&vocab=%vocab"),
        toCSID: "cspace.util.shortIdentifierToCSID",
        preInitFunction: "cspace.autocomplete.popup.miniView.renderer.preInit"
    });

    cspace.autocomplete.popup.miniView.renderer.preInit = function (that) {
        // Process mini view model for quick render.
        that.prepareModelForRender = function () {
            var link = fluid.stringTemplate(that.options.url, {
                recordType: that.options.recordType,
                vocab: that.options.vocab,
                csid: fluid.invokeGlobalFunction(that.options.toCSID, [
                    that.options.urn
                ])
            });
            that.applier.requestChange("miniView-link", link);
        };
    };

    fluid.fetchResources.primeCacheFromResources("cspace.autocomplete.popup.miniView.renderer");

    cspace.autocomplete.popup.miniView.preInit = function (that) {
        that.onContext = function () {
            that.options.context = that.model.attributes.type + "-miniView";
        };
        that.onModel = function (attributes) {
            that.applier.requestChange("attributes", attributes);
            that.events.onContext.fire();
            that.events.onReady.fire();
        };
        that.onReady = function () {
            that.dataSource.get({
                csid: that.options.toCSID ?
                    that.urnToCSID.convert(that.model.attributes.urn) :
                    that.model.attributes.csid,
                recordType: that.model.attributes.type,
                vocab: that.model.attributes.namespace
            }, function (basic) {
                that.applier.requestChange("basic", basic);
            });
        };
        that.applier.modelChanged.addListener("basic", function () {
            that.events.onRender.fire();
            that.events.onShow.fire();
        });
        that.hide = function () {
            clearTimeout(that.options.showTimer);
            that.container.hide();
        };
        that.show = function () {
            var options = that.options,
                showTimer = that.options.showTimer;
            if (showTimer) {
                clearTimeout(showTimer);
            }
            that.options.showTimer = setTimeout(function () {
                that.container.show();
            }, options.delay || 1);
        };
    };
    /* miniView component */

    // Autocomple popup component.
    fluid.defaults("cspace.autocomplete.popup", {
        gradeNames: "fluid.rendererComponent",
        selectors: {
            addToPanel: ".csc-autocomplete-addToPanel",
            authorityItem: ".csc-autocomplete-authorityItem",
            noMatches: ".csc-autocomplete-noMatches",
            matches: ".csc-autocomplete-matches",
            matchItem: ".csc-autocomplete-matchItem",
            matchItemContent: ".csc-autocomplete-matchItem-content",
            addTermTo: ".csc-autocomplete-addTermTo"
        },
        invokers: {
            open: "cspace.autocomplete.popup.open",
            addRowHover: "cspace.autocomplete.popup.addRowHover"
        },
        styles: {
            authoritiesSelect: "cs-autocomplete-authorityItem-select",
            matchesSelect: "cs-autocomplete-matchItem-select",
            nonPreferred: "cs-autocomplete-nonPreferred",
            nonPreferredDisabled: "cs-autocomplete-nonPreferredDisabled"
        },
        repeatingSelectors: ["matchItem", "authorityItem"],
        preInitFunction: "cspace.autocomplete.popup.preInit",
        produceTree: "cspace.autocomplete.produceTree",
        // Template for popup component.
        resources: {
            template: {
                expander: {
                    type: "fluid.deferredInvokeCall",
                    func: "cspace.specBuilder",
                    args: {
                        forceCache: true,
                        fetchClass: "slowTemplate",
                        url: "%webapp/html/components/AutocompleteAddPopup.html"
                    }
                }
            }
        },
        components: {
            // Same old event holder.
            eventHolder: "{eventHolder}",
            vocab: "{vocab}",
            miniView: {
                type: "cspace.autocomplete.popup.miniView",
                container: ".cs-autocomplete-popup-miniView",
                createOnEvent: "afterRender"
            }
        },
        strings: {},
        parentBundle: "{globalBundle}"
    });

    fluid.demands("cspace.autocomplete.popup.open", "cspace.autocomplete.popup", {
        funcName: "cspace.autocomplete.popup.open",
        args: "{cspace.autocomplete.popup}"
    });

    fluid.demands("cspace.autocomplete.popup.open", ["cspace.autocomplete.popup", "cspace.hierarchyAutocomplete", "cspace.nonAuthority"], {
        funcName: "cspace.autocomplete.popup.open",
        args: ["{cspace.autocomplete.popup}", "newTermName"]
    });

    cspace.autocomplete.popup.open = function (that, extraSelectables) {
        // Render the popup view.
        // Attach all keyboard related abilities.
        that.renderer.refreshView();

        var input = fluid.unwrap(that.options.inputField),
            container = that.container,
            activatables, selectables,
            matchItemContent = that.locate("matchItemContent");
        activatables = that.locate("authorityItem").add(matchItemContent);
        fluid.activatable(activatables, that.activateFunction);
        selectables = $(activatables).add(input);
        if (extraSelectables) {
            selectables = selectables.add(that.locate(extraSelectables));
        }

        that.selectable.selectables = selectables;
        that.selectable.selectablesUpdated();
        container.show();
        container.dialog("open");
        // NB: on IE8, the above creates a cyclically linked DOM structure! The following
        // or variant may help with styling issues container.appendTo(document.body);
        container.position({
            my: "left top",
            at: "left bottom",
            of: that.options.inputField,
            collision: "none"
        });

        // Add hover for all the elements
        that.addRowHover(that.miniView, matchItemContent, that.model.matches, that.container.find(".inner").width());
    };

    cspace.autocomplete.popup.addRowHover = function (miniView, elements, matches, left) {
        // Add hoever, focus functionality related to the mini view.
        var timeout,
            openMiniView = function (el) {
                var currentTarget = $(el.currentTarget),
                    index = currentTarget.attr("id").split(":")[1];

                index = (index === "") ? 0 : index * 1;
                miniView.container.css({
                    top: currentTarget.position().top,
                    left: left + 10
                });
                miniView.events.onModel.fire(matches[index]);
            },
            closeMiniView = function () {
                miniView.events.onHide.fire();
            };

        miniView.container
            .mouseenter(function () {
                if (timeout) {
                    clearTimeout(timeout);
                }
            }).mouseleave(function (el) {
                closeMiniView(el);
            });

        elements
            .focusin(function (el) {
                openMiniView(el);
            }).focusout(function (el) {
                closeMiniView(el);
            }).hover(function (el) {
                clearTimeout(timeout);
                closeMiniView(el);
                openMiniView(el);
            }, function (el) {
                timeout = setTimeout(function () {
                    closeMiniView(el);
                }, 500);
            });
    };

    fluid.fetchResources.primeCacheFromResources("cspace.autocomplete.popup");

    function updateAuthoritatively(that, termRecord) {
        // Handle update of the actual hidden model-bound field when
        // the autocomplete value is set.
        if (that.hiddenInput.val() &&
            termRecord.urn === that.hiddenInput.val() &&
            that.autocompleteInput.val() === termRecord.displayName) {
            return;
        }
        if (that.hiddenInput.val() !== termRecord.urn) {
            that.hiddenInput.val(termRecord.urn);
            that.hiddenInput.change();
        }
        fluid.log("New value " + termRecord.displayName);
        that.autocompleteInput.val(termRecord.displayName);
        that.applier.requestChange("baseRecord", fluid.copy(termRecord));
        that.applier.requestChange("term", termRecord.displayName);
        if (that.autocomplete) {
            that.autocomplete.suppress();
        }
    }

    // find the HIGHEST ancestor which has non-default position
    function findTopRelative(node) {
        var lastPos;
        while (node) {
            var jNode = $(node);
            if (jNode.is("body")) {
                return lastPos || jNode;
            }
            var position = jNode.css("position");
            if (position === "relative" || position === "absolute") {
                lastPos = jNode;
            }
            node = node.parentNode;
        }
    }

    cspace.autocomplete.handlePermissions = function (applier, model, resolve, options, permission) {
        // Filter authorities from configuration based on permissions.
        var types = fluid.transform(model.authorities, function (auth) {
            // We only need an authority not the vocabulary.
            return auth.type.split("-")[0];
        });
        options.oneOf = types;

        var authorities = fluid.remove_if(fluid.copy(model.authorities), function (auth) {
            return !cspace.permissions.resolve({
                resolver: options.resolver,
                permission: permission,
                // We only need an authority not the vocabulary.
                target: auth.type.split("-")[0]
            });
        });
        applier.requestChange("authorities", authorities);
    };

    cspace.autocomplete.buttonAdjustor = function (closeButton, model, hide) {
        closeButton[model.term === model.baseRecord.displayName || hide ? "hide": "show"]();
    };

    var selectAuthority = function (that, model, directModel, newTermUrl) {
        // Common select authority functionality used by all autocompletes.
        fluid.merge(null, model, {
            fields: {
                displayName: that.model.term
            },
            _view: "autocomplete"
        });
        that.buttonAdjustor(true); // Hide the button. It will be replaced by the spinnder to indicate selection is being saved (CSPACE-2091).
        that.newTermSource.set(model, directModel, function (response) {
            if (!response) {
                that.displayErrorMessage(fluid.stringTemplate(that.resolveMessage("emptyResponse"), {
                    url: newTermUrl
                }));
                return;
            }
            if (response.isError === true) {
                fluid.each(response.messages, function (message) {
                    that.displayErrorMessage(message);
                });
                return;
            }
            updateAuthoritatively(that, response);
            that.eventHolder.events.afterSelectAuthority.fire();
        }, cspace.util.provideErrorCallback(that, newTermUrl, "errorWriting"));
    };

    // Generic select authority invoker implementation.
    cspace.autocomplete.selectAuthority = function (that, key) {
        var authority = that.model.authorities[key],
            directModel = {termUrl: authority.url},
            newTermUrl = that.newTermSource.resolveUrl(directModel),
            model = {};
        selectAuthority(that, model, directModel, newTermUrl);
    };

    // Select authority specific to structured objects.
    cspace.autocomplete.selectAuthorityStructuredObjects = function (that, recordModel, changeTracker, messageBar, fieldsToIgnore, schema, key) {
        var authority = that.model.authorities[key],
            directModel = {termUrl: authority.type},
            newTermUrl = that.newTermSource.resolveUrl(directModel),
            model;
        if (!that.model.term) {
            that.revertState();
            messageBar.show(that.options.parentBundle.resolve("autocomplete-structuredObjects-enterName"), null, true);
            that.eventHolder.events.afterSelectAuthority.fire();
            return;
        }
        if (authority.createFromExisting) {
            if (changeTracker.unsavedChanges) {
                messageBar.show(that.options.parentBundle.resolve("autocomplete-structuredObjects-pleaseSave"), null, false);
            }
            model = fluid.copy(recordModel);
            fluid.each(fieldsToIgnore, function (fieldPath) {
                fluid.set(model, fieldPath);
            });
        } else {
            model = cspace.util.getBeanValue({}, authority.type, schema);
        }
        selectAuthority(that, model, directModel, newTermUrl);
    };

    // Revert autocomplete value to its original.
    cspace.autocomplete.revertState = function (that) {
        updateAuthoritatively(that, that.model.baseRecord);
        that.buttonAdjustor();
        that.popup.close();
    };

    // Select a match from the list of queried matches.
    cspace.autocomplete.selectMatch = function (that, key) {
        var match = that.model.matches[key],
            rowDisabled = that.options.elPaths.rowDisabled;
        if (match[rowDisabled]) {
            return;
        }
        updateAuthoritatively(that, match);
        that.buttonAdjustor();
        that.eventHolder.events.afterSelectMatch.fire();
    };

    // Select a match from the list of queried matches, specific to te case
    // where confirmation is needed (e.g. picking narrower that has different
    // broader).
    cspace.autocomplete.selectMatchConfirm = function (that, key) {
        var match = that.model.matches[key];
        that.broaderDataSource.get({recordType: match.type, csid: match.csid}, function (response) {
            if (!response.broader) {
                updateAuthoritatively(that, match);
                that.buttonAdjustor();
                that.eventHolder.events.afterSelectMatch.fire();
                return;
            }
            that.confirmation.open("cspace.confirmation.deleteDialog", undefined, {
                listeners: {
                    onClose: function (userAction) {
                        if (userAction === "act") {
                            updateAuthoritatively(that, match);
                            that.buttonAdjustor();
                        } else {
                            that.revertState();
                        }
                        that.eventHolder.events.afterSelectMatch.fire();
                    }
                },
                termMap: [
                    match["label"],
                    response.broader["label"]
                ],
                model: {
                    messages: [ "autocomplete-dialog-primaryMessage" ],
                    messagekeys: {
                        actText: "autocomplete-dialog-actText",
                        actAlt: "autocomplete-dialog-actAlt",
                        cancelText: "autocomplete-dialog-cancelText",
                        cancelAlt: "autocomplete-dialog-cancelAlt"
                    }
                },
                parentBundle: that.options.parentBundle
            });
        });
    };

})(jQuery, fluid);


text:
using CitySimulator.Render;

namespace CitySimulator {
    static class Program {
        public static string AssetsFolder = "D:\\projects\\CitySimulatorData\\Assets\\";
        public static string SavesFolder = "D:\\projects\\CitySimulatorData\\Saves\\";

        /// <summary>
        /// Updates per second
        /// </summary>
        public static float Ups = 30;

        public static Cache<string, Texture> TextureCache = new Cache<string, Texture>(s => new Texture(s));

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main() {
            //var frm = new GameForm();
            //frm.GameLoop();

            using (var game = new TkGameWindow()) {
                game.Run(Ups);
            }
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
package org.dylanfoundry.deft.filetypes.dylan.psi;

import java.util.List;
import org.jetbrains.annotations.*;
import com.intellij.psi.PsiElement;

public interface DylanMethodTail extends DylanCompositeElement {

}


text:
require File.dirname(__FILE__) + '/../../../spec_helper'
require File.dirname(__FILE__) + '/parser_spec_helper'

shared_examples 'empty use archetypes' do
  describe 'empty use is assigned nil to be valid archtype' do
    it 'is not nil' do
      expect(subject).not_to be_nil
    end
  end

  describe 'description for use is nil' do
    it 'use is nil' do
      expect(subject.description.details['en'].use).to be_nil
    end
  end
end

describe 'Archetypes, which has empty use' do
  adls = ['openEHR-EHR-OBSERVATION.operation_record.v1.adl',
         'openEHR-EHR-CLUSTER.exam-abdomen.v1.adl',
         'openEHR-EHR-OBSERVATION.uterine_contractions.v1.adl',
         'openEHR-EHR-CLUSTER.exam-uterine_cervix.v1.adl',
         'openEHR-EHR-CLUSTER.exam-uterus.v1.adl']

  adls.each do |adl|
    subject { adl14_archetype(adl) }
    it_should_behave_like 'empty use archetypes'
  end
end


text:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class MemberPanelValidator : MonoBehaviour {

    public GameObject node1, node2, prop,add;

	// Use this for initialization
	void Start () {

	}

	// Update is called once per frame
	void Update () {
        if (node1.GetComponent<LoadInputValue>().index==node2.GetComponent<LoadInputValue>().index||node1.GetComponent<LoadInputValue>().list.Length == 0 || node2.GetComponent<LoadInputValue>().list.Length == 0 || prop.GetComponent<SelectButtonValueStore>().state == -1)
            add.GetComponent<Button>().interactable = false;
        else
            add.GetComponent<Button>().interactable = true;

	}
}


text:
from oic.utils.keyio import keybundle_from_local_file
from oic.utils.userinfo import UserInfo

__author__ = 'rohe0002'

import logging
import re

from oic.utils.http_util import *
from oic.oic.message import OpenIDSchema

LOGGER = logging.getLogger("")
hdlr = logging.FileHandler('oc3cp.log')
formatter = logging.Formatter('%(asctime)s %(name)s:%(levelname)s %(message)s')
hdlr.setFormatter(formatter)
LOGGER.addHandler(hdlr)
LOGGER.setLevel(logging.DEBUG)

# ----------------------------------------------------------------------------

#noinspection PyUnusedLocal
def verify_client(environ, req, cdb):
    identity = req["client_id"]
    secret = req["client_secret"]
    if identity:
        if identity in cdb:
            if cdb[identity]["client_secret"] == secret:
                return True

    return False

#noinspection PyUnusedLocal
def user_info(oicsrv, userdb, sub, client_id="", user_info_claims=None):
    #print >> sys.stderr, "claims: %s" % user_info_claims

    identity = userdb[sub]
    if user_info_claims:
        result = {}
        claims = user_info_claims["claims"]
        for key, restr in claims.items():
            try:
                result[key] = identity[key]
            except KeyError:
                if restr == {"essential": True}:
                    raise Exception("Missing property '%s'" % key)
    else:
        result = identity

    return OpenIDSchema(**result)

USER2MODE = {"diana": "aggregate",
             "upper": "distribute",
             "babs": "aggregate"}

#noinspection PyUnusedLocal
def claims_mode(info, uid):
    if USER2MODE[uid] == "aggregate":
        return True
    else:
        return False

FUNCTIONS = {
    "verify_client": verify_client,
    "userinfo": user_info,
    "claims_mode": claims_mode
}

# ----------------------------------------------------------------------------

#noinspection PyUnusedLocal
def userinfo(environ, start_response, handle):
    _oas = environ["oic.oas"]

    return _oas.userinfo_endpoint(environ, start_response, LOGGER)

#noinspection PyUnusedLocal
def check_id(environ, start_response, handle):
    _oas = environ["oic.oas"]

    return _oas.check_id_endpoint(environ, start_response, LOGGER)

#noinspection PyUnusedLocal
def op_info(environ, start_response, handle):
    _oas = environ["oic.oas"]

    return _oas.providerinfo_endpoint(environ, start_response, LOGGER)

#noinspection PyUnusedLocal
def userclaims(environ, start_response, handle):
    _oas = environ["oic.oas"]

    LOGGER.info("claims_endpoint")
    return _oas.claims_endpoint(environ, start_response, LOGGER)

#noinspection PyUnusedLocal
def registration(environ, start_response, handle):
    _oas = environ["oic.oas"]

    return _oas.registration_endpoint(environ, start_response)

#noinspection PyUnusedLocal
def userclaimsinfo(environ, start_response, handle):
    _oas = environ["oic.oas"]

    LOGGER.info("claims_info_endpoint")
    return _oas.claims_info_endpoint(environ, start_response, LOGGER)

# ----------------------------------------------------------------------------

def static(environ, start_response, path):

    _txt = open(path).read()
    if "x509" in path:
        content = "text/xml"
    else:
        content = "application/json"

    resp = Response(_txt, content=content)
    return resp(environ, start_response)

# ----------------------------------------------------------------------------

from oic.oic.provider import UserinfoEndpoint
#from oic.oic.provider import CheckIDEndpoint
from oic.oic.provider import RegistrationEndpoint
from oic.oic.claims_provider import UserClaimsEndpoint
from oic.oic.claims_provider import UserClaimsInfoEndpoint

ENDPOINTS = [
    UserinfoEndpoint(userinfo),
    #CheckIDEndpoint(check_id),
    RegistrationEndpoint(registration),
    UserClaimsEndpoint(userclaims),
    UserClaimsInfoEndpoint(userclaimsinfo)
]

URLS = [
    (r'^.well-known/openid-configuration', op_info)
]

for endp in ENDPOINTS:
    URLS.append(("^%s$" % endp.etype, endp))

def application(environ, start_response):
    """
    The main WSGI application. Dispatch the current request to
    the functions from above and store the regular expression
    captures in the WSGI environment as  `oic.url_args` so that
    the functions from above can access the url placeholders.

    If nothing matches call the `not_found` function.

    :param environ: The HTTP application environment
    :param start_response: The application to run when the handling of the
        request is done
    :return: The response as a list of lines
    """
    global OAS

    #user = environ.get("REMOTE_USER", "")
    path = environ.get('PATH_INFO', '').lstrip('/')
    kaka = environ.get("HTTP_COOKIE", '')

    if kaka:
        handle = parse_cookie(OAS.name, OAS.seed, kaka)
        LOGGER.debug("Cookie: %s" % (kaka,))
    else:
        handle = ""

    environ["oic.oas"] = OAS

    LOGGER.info("path: %s" % path)
    if path in OAS.cert or path in OAS.jwk:
        return static(environ, start_response, path)
    else:
        for regex, callback in URLS:
            match = re.search(regex, path)
            if match is not None:
                try:
                    environ['oic.url_args'] = match.groups()[0]
                except IndexError:
                    environ['oic.url_args'] = path
                return callback(environ, start_response, handle)

    resp = NotFound("Couldn't find the side you asked for!")
    return resp(environ, start_response)

# ----------------------------------------------------------------------------

USERDB = {
    "diana": {
        "geolocation": {"longitude": 20.3076, "latitude": 63.8206},
    },
    "upper": {
        "geolocation": {"longitude": 17.0393, "latitude": 59.65075},
    },
    "babs": {
        "geolocation": {"longitude": 4.8890, "latitude": 52.3673},
    }
}

SERVER_DB = {}

if __name__ == '__main__':
    import argparse
    import json

    from cherrypy import wsgiserver
    from cherrypy.wsgiserver import ssl_builtin

    from oic.oic.claims_provider import ClaimsServer
    from oic.utils.sdb import SessionDB

    parser = argparse.ArgumentParser()
    parser.add_argument('-v', dest='verbose', action='store_true')
    parser.add_argument('-d', dest='debug', action='store_true')
    parser.add_argument('-p', dest='port', default=8093, type=int)
    parser.add_argument(dest="config")
    args = parser.parse_args()

    cdb = json.loads(open("claims_client.json").read())
    userinfo = UserInfo(USERDB)

    # in memory session storage

    config = json.loads(open(args.config).read())
    OAS = ClaimsServer(config["issuer"], SessionDB(), cdb, userinfo,
                       verify_client)

    if "keys" in config:
        for typ, info in config["keys"].items():
            OAS.keyjar.add_kb("", keybundle_from_local_file(info["key"], "rsa",
                                                            ["ver", "sig"]))
            try:
                OAS.jwks_uri.append(info["jwk"])
            except KeyError:
                pass

    #print URLS
    if args.debug:
        OAS.debug = True

    OAS.endpoints = ENDPOINTS
    if args.port == 80:
        OAS.baseurl = config["baseurl"]
    else:
        if config["baseurl"].endswith("/"):
            config["baseurl"] = config["baseurl"][:-1]
        OAS.baseurl = "%s:%d" % (config["baseurl"], args.port)

    if not OAS.baseurl.endswith("/"):
        OAS.baseurl += "/"

    OAS.claims_userinfo_endpoint = "%s%s" % (
        OAS.baseurl, UserClaimsInfoEndpoint.etype)

    SRV = wsgiserver.CherryPyWSGIServer(('0.0.0.0', args.port), application)
    SRV.ssl_adapter = ssl_builtin.BuiltinSSLAdapter("certs/server.crt",
                                                    "certs/server.key")

    LOGGER.info("Starting server")
    try:
        SRV.start()
    except KeyboardInterrupt:
        SRV.stop()


text:
import EmberObject from '@ember/object';
import PestoItemsSortingMixinMixin from 'ember-pesto/mixins/pesto-items-sorting';
import { module, test } from 'qunit';

module('Unit | Mixin | pesto items sorting mixin');

// Replace this with your real tests.
test('it works', function(assert) {
  let PestoItemsSortingMixinObject = EmberObject.extend(PestoItemsSortingMixinMixin);
  let subject = PestoItemsSortingMixinObject.create();
  assert.ok(subject);
});


text:
[![Stories in Ready](https://badge.waffle.io/Adiqq/aurelia-docker-dotnet.png?label=ready&title=Ready)](https://waffle.io/Adiqq/aurelia-docker-dotnet)
# aurelia-docker-dotnet

## Overview

This project uses [Docker](https://docs.docker.com/) for contenerization.

There are two containers, one for API and one for front-end.

### Front-end

Front-end project uses [Aurelia](http://aurelia.io/) with initial structure generated
by [Yeoman](http://yeoman.io/), [generator-aurelia](https://github.com/zewa666/generator-aurelia).

It uses [gulp-watch](https://www.npmjs.com/package/gulp-watch) and
[browsersync](https://www.browsersync.io/),
 so our changes in code will be automatically applied.

### API

Back-end API uses [.NET Core](https://docs.microsoft.com/pl-pl/dotnet/articles/core/index)
with [ASP.NET Core](https://docs.asp.net/en/latest/).

It uses [dotnet-watch](https://github.com/aspnet/dotnet-watch), so after we run our components,
changes to code will be automatically applied to server.

### Docker

We will use [docker-compose](https://docs.docker.com/compose/overview/) to simplify
containers management.

We are going to use [Docker for Windows](https://docs.docker.com/docker-for-windows/).

After installation, open Docker Settings and on Shared Drives tab, set your drive as shared.
It's necessary to mount project's code to containers, so if e.g. your project is on C drive,
you need to share C.

Now, we need to clone our git project, `git clone https://github.com/Adiqq/aurelia-docker-dotnet.git`

Next, we execute `install.bat`, it will execute powershell script as administrator.
This script will install [Chocolatey](https://chocolatey.org/), then Chocolatey will install
[Node.js](https://nodejs.org/en/), [Gulp](http://gulpjs.com/) and [jspm](http://jspm.io/).
It will also install all [npm](https://www.npmjs.com/) and jspm dependencies.

We can also install dependencies manually:
`npm install && jspm install`

Now, we can run `run-docker.bat`, this will execute powershell script that simply calls `docker-compose up`.
It will build our containers and run them.

Alternatively, we can simply open cmd/powershell and call it ourselves from project's directory.

We are mainly going to use few, useful docker-compose commands:

`docker-compose up` - start our containers (also build if necessary)

`docker-compose build`- build containers

`docker-compose build --no-cache`- rebuild from scratch

In case we didn't closed our containers correctly, we can use:

`docker-compose stop` or `docker-compose kill`

Alternatively, we can use:

`docker ps` to list all running components and then kill them by id:

`docker kill 'container id'`

### Problems

In case of errors or problems, we can attach to container:

e.g `/api/project.lock.json(1,0): error NU1009: The expected lock file doesn't exist. Please run "dotnet restore" to generate a new lock file.`

First we need to open new cmd or powershell window and use `docker ps`

We need to find id of container that we need, in this case API.

Next, we type `docker exec -i -t ourContainerId /bin/bash`.

We should be logged to container's bash, next we type `dotnet restore`

If everything went ok, we can type `exit` to dettach from container.


text:
<?xml version="1.0" encoding="UTF-8"?>
<tei xmlns="http://www.tei-c.org/ns/1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:mml="http://www.w3.org/1998/Math/MathML">
	<teiHeader>
		<fileDesc>
			<sourceDesc>
				<biblStruct>
					<analytic>
						<author>

						<affiliation>
							<orgName type="laboratory">Laboratoire de Biologie Cellulaire</orgName>,
							<orgName type="institution">INRA</orgName>,
							<address>
								<postCode>78026</postCode>
								<settlement>Versailles Cedex</settlement>,
							</address>
						</affiliation>

						</author>
					</analytic>
				</biblStruct>
			</sourceDesc>
		</fileDesc>
	</teiHeader>
</tei>


text:
from django.conf.urls import patterns, include, url
from django.conf.urls.static import static
from django.conf import settings
from django.views.generic import TemplateView

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    url(r'^$', TemplateView.as_view(template_name='base.html')),

    # Examples:
    # url(r'^$', 'hsvpy.views.home', name='home'),
    # url(r'^hsvpy/', include('hsvpy.foo.urls')),

    # Uncomment the admin/doc line below to enable admin documentation:
    url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    url(r'^admin/', include(admin.site.urls)),
    url(r'^stories/', include('stories.urls')),
)

# Uncomment the next line to serve media files in dev.
# urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

if settings.DEBUG:
    import debug_toolbar
    urlpatterns += patterns('',
                            url(r'^__debug__/', include(debug_toolbar.urls)),
                            )


text:
using Newtonsoft.Json;

using Vulpecula.Models.Base;

namespace Vulpecula.Models
{
    public class SecretMail : StatusBase
    {
        [JsonProperty("recipient")]
        public User Recipient { get; set; }

        [JsonProperty("recipient_id")]
        public long RecipientId { get; set; }

        [JsonProperty("recipient_screen_name")]
        public string RecipientScreenName { get; set; }

        [JsonProperty("sender")]
        public User Sender { get; set; }

        [JsonProperty("sender_id")]
        public long SenderId { get; set; }

        [JsonProperty("sender_screen_name")]
        public string SenderScreenName { get; set; }
    }
}


text:
package com.microsoft.azure.batch.protocol.models;

import java.util.List;

/**
 * A node agent SKU supported by the Batch service.
 * The Batch node agent is a program that runs on each node in the pool, and
 * provides the command-and-control interface between the node and the Batch
 * service. There are different implementations of the node agent, known as
 * SKUs, for different operating systems.
 */
public class NodeAgentSku {
    /**
     * The node agent SKU id.
     */
    private String id;

    /**
     * The list of images verified to be compatible with this node agent SKU.
     * This collection is not exhaustive (the node agent may be compatible
     * with other images).
     */
    private List<ImageReference> verifiedImageReferences;

    /**
     * The type of operating system compatible with the node agent SKU.
     * Possible values include: 'linux', 'windows', 'unmapped'.
     */
    private OSType osType;

    /**
     * Get the id value.
     *
     * @return the id value
     */
    public String id() {
        return this.id;
    }

    /**
     * Set the id value.
     *
     * @param id the id value to set
     * @return the NodeAgentSku object itself.
     */
    public NodeAgentSku withId(String id) {
        this.id = id;
        return this;
    }

    /**
     * Get the verifiedImageReferences value.
     *
     * @return the verifiedImageReferences value
     */
    public List<ImageReference> verifiedImageReferences() {
        return this.verifiedImageReferences;
    }

    /**
     * Set the verifiedImageReferences value.
     *
     * @param verifiedImageReferences the verifiedImageReferences value to set
     * @return the NodeAgentSku object itself.
     */
    public NodeAgentSku withVerifiedImageReferences(List<ImageReference> verifiedImageReferences) {
        this.verifiedImageReferences = verifiedImageReferences;
        return this;
    }

    /**
     * Get the osType value.
     *
     * @return the osType value
     */
    public OSType osType() {
        return this.osType;
    }

    /**
     * Set the osType value.
     *
     * @param osType the osType value to set
     * @return the NodeAgentSku object itself.
     */
    public NodeAgentSku withOsType(OSType osType) {
        this.osType = osType;
        return this;
    }

}


text:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { DetailModule } from '../detail/detail.module';
import { OverviewComponent } from './overview.component';

@NgModule({
  imports: [
    CommonModule,
    DetailModule,
  ],
  exports: [
    OverviewComponent,
  ],
  declarations: [
    OverviewComponent,
  ],
})
export class OverviewModule { }


text:
package org.jhotdraw.draw;

import edu.umd.cs.findbugs.annotations.Nullable;
import org.jhotdraw.draw.tool.Tool;
import java.awt.Container;
import java.awt.Cursor;
import java.beans.*;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import org.jhotdraw.beans.AbstractBean;

/**
 * DrawingEditorProxy.
 *

 * Design Patterns
 *
 *
Proxy

 * To remove the need for null-handling, {@code AbstractTool} makes use of
 * a proxy for {@code DrawingEditor}.
 * Subject: {@link DrawingEditor}; Proxy: {@link DrawingEditorProxy};
 * Client: {@link org.jhotdraw.draw.tool.AbstractTool}.
 *

 *
 *
 * @author Werner Randelshofer
 * @version $Id: DrawingEditorProxy.java 717 2010-11-21 12:30:57Z rawcoder $
 */
public class DrawingEditorProxy extends AbstractBean implements DrawingEditor {
    @Nullable private DrawingEditor target;

    private class Forwarder implements PropertyChangeListener, Serializable {
    @Override
          public void propertyChange(PropertyChangeEvent evt) {
              firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
          }
    }
    private Forwarder forwarder;

    /** Creates a new instance. */
    public DrawingEditorProxy() {
        forwarder = new Forwarder();
    }

    /**
     * Sets the target of the proxy.
     */
    public void setTarget(@Nullable DrawingEditor newValue) {
        if (target != null) {
            target.removePropertyChangeListener(forwarder);
        }
        this.target = newValue;
        if (target != null) {
            target.addPropertyChangeListener(forwarder);
        }
    }
    /**
     * Gets the target of the proxy.
     */
    @Nullable public DrawingEditor getTarget() {
        return target;
    }

    @Override
    public void add(DrawingView view) {
        target.add(view);
    }

    @Override
    public void remove(DrawingView view) {
        target.remove(view);
    }

    @Override
    public Collection<DrawingView> getDrawingViews() {
        return target.getDrawingViews();
    }

    @Override
    public DrawingView getActiveView() {
        return (target == null) ? null : target.getActiveView();
    }

    @Override
    public void setActiveView(DrawingView newValue) {
        target.setActiveView(newValue);
    }

    @Nullable
    public DrawingView getFocusedView() {
        return (target == null) ? null : target.getActiveView();
    }

    @Override
    public void setTool(Tool t) {
        target.setTool(t);
    }

    @Override
    public Tool getTool() {
        return target.getTool();
    }

    @Override
    public void setCursor(Cursor c) {
        target.setCursor(c);
    }

    @Override
    public DrawingView findView(Container c) {
        return target.findView(c);
    }

    @Override
    public <T> void setDefaultAttribute(AttributeKey<T> key, T value) {
        target.setDefaultAttribute(key, value);
    }

    @Override
    public <T> T getDefaultAttribute(AttributeKey<T> key) {
        return target.getDefaultAttribute(key);
    }

    @Override
    public void applyDefaultAttributesTo(Figure f) {
        target.applyDefaultAttributesTo(f);
    }

    @Override
    public Map<AttributeKey, Object> getDefaultAttributes() {
        return target.getDefaultAttributes();
    }

    @Override
    public void setEnabled(boolean newValue) {
        target.setEnabled(newValue);
    }

    @Override
    public boolean isEnabled() {
        return target.isEnabled();
    }

    @Override
    public <T> void setHandleAttribute(AttributeKey<T> key, T value) {
        target.setHandleAttribute(key, value);
    }

    @Override
    public <T> T getHandleAttribute(AttributeKey<T> key) {
        return target.getHandleAttribute(key);
    }

    @Override
    public void setInputMap(InputMap newValue) {
        target.setInputMap(newValue);
    }

    @Override
    public InputMap getInputMap() {
        return target.getInputMap();
    }

    @Override
    public void setActionMap(ActionMap newValue) {
        target.setActionMap(newValue);
    }

    @Override
    public ActionMap getActionMap() {
        return target.getActionMap();
    }
}


text:
// +build linux

package cm

import (
	"fmt"
	"testing"

	"github.com/stretchr/testify/assert"

	"k8s.io/kubernetes/pkg/util/mount"
)

type fakeMountInterface struct {
	mountPoints []mount.MountPoint
}

func (mi *fakeMountInterface) Mount(source string, target string, fstype string, options []string) error {
	return fmt.Errorf("unsupported")
}

func (mi *fakeMountInterface) Unmount(target string) error {
	return fmt.Errorf("unsupported")
}

func (mi *fakeMountInterface) List() ([]mount.MountPoint, error) {
	return mi.mountPoints, nil
}

func (mi *fakeMountInterface) IsLikelyNotMountPoint(file string) (bool, error) {
	return false, fmt.Errorf("unsupported")
}

func fakeContainerMgrMountInt() mount.Interface {
	return &fakeMountInterface{
		[]mount.MountPoint{
			{
				Device: "cgroup",
				Type:   "cgroup",
				Opts:   []string{"rw", "relatime", "cpuset"},
			},
			{
				Device: "cgroup",
				Type:   "cgroup",
				Opts:   []string{"rw", "relatime", "cpu"},
			},
			{
				Device: "cgroup",
				Type:   "cgroup",
				Opts:   []string{"rw", "relatime", "cpuacct"},
			},
			{
				Device: "cgroup",
				Type:   "cgroup",
				Opts:   []string{"rw", "relatime", "memory"},
			},
		},
	}
}

func TestCgroupMountValidationSuccess(t *testing.T) {
	assert.Nil(t, validateSystemRequirements(fakeContainerMgrMountInt()))
}

func TestCgroupMountValidationMemoryMissing(t *testing.T) {
	mountInt := &fakeMountInterface{
		[]mount.MountPoint{
			{
				Device: "cgroup",
				Type:   "cgroup",
				Opts:   []string{"rw", "relatime", "cpuset"},
			},
			{
				Device: "cgroup",
				Type:   "cgroup",
				Opts:   []string{"rw", "relatime", "cpu"},
			},
			{
				Device: "cgroup",
				Type:   "cgroup",
				Opts:   []string{"rw", "relatime", "cpuacct"},
			},
		},
	}
	assert.Error(t, validateSystemRequirements(mountInt))
}

func TestCgroupMountValidationMultipleSubsytem(t *testing.T) {
	mountInt := &fakeMountInterface{
		[]mount.MountPoint{
			{
				Device: "cgroup",
				Type:   "cgroup",
				Opts:   []string{"rw", "relatime", "cpuset", "memory"},
			},
			{
				Device: "cgroup",
				Type:   "cgroup",
				Opts:   []string{"rw", "relatime", "cpu"},
			},
			{
				Device: "cgroup",
				Type:   "cgroup",
				Opts:   []string{"rw", "relatime", "cpuacct"},
			},
		},
	}
	assert.Nil(t, validateSystemRequirements(mountInt))
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MugLyon.SignalR.Demo.LiveCoding.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Chat()
        {
            return View();
        }

        public ActionResult ChatWithHub()
        {
            return View();
        }

        public ActionResult MoveShape()
        {
            return View();
        }

        public ActionResult Worker()
        {
            return View();
        }
    }
}


text:
'use strict';

var _vue = require('vue');

var _vue2 = _interopRequireDefault(_vue);

var _vueRouter = require('vue-Router');

var _vueRouter2 = _interopRequireDefault(_vueRouter);

var _vueTouch = require('vue-touch');

var _vueTouch2 = _interopRequireDefault(_vueTouch);

var _index = require('../lib/index.js');

var _index2 = _interopRequireDefault(_index);

var _App = require('./App.vue');

var _App2 = _interopRequireDefault(_App);

var _TabView = require('./view/TabView.vue');

var _TabView2 = _interopRequireDefault(_TabView);

var _ButtonView = require('./view/ButtonView.vue');

var _ButtonView2 = _interopRequireDefault(_ButtonView);

var _LoadingView = require('./view/LoadingView.vue');

var _LoadingView2 = _interopRequireDefault(_LoadingView);

var _ToastView = require('./view/ToastView.vue');

var _ToastView2 = _interopRequireDefault(_ToastView);

var _ShareView = require('./view/ShareView.vue');

var _ShareView2 = _interopRequireDefault(_ShareView);

var _LineView = require('./view/LineView.vue');

var _LineView2 = _interopRequireDefault(_LineView);

var _AlertView = require('./view/AlertView.vue');

var _AlertView2 = _interopRequireDefault(_AlertView);

var _AdView = require('./view/AdView.vue');

var _AdView2 = _interopRequireDefault(_AdView);

var _SwitchView = require('./view/SwitchView.vue');

var _SwitchView2 = _interopRequireDefault(_SwitchView);

var _ModelView = require('./view/ModelView.vue');

var _ModelView2 = _interopRequireDefault(_ModelView);

var _MaskView = require('./view/MaskView.vue');

var _MaskView2 = _interopRequireDefault(_MaskView);

var _AnnouncementView = require('./view/AnnouncementView.vue');

var _AnnouncementView2 = _interopRequireDefault(_AnnouncementView);

var _InputView = require('./view/InputView.vue');

var _InputView2 = _interopRequireDefault(_InputView);

var _AgreementView = require('./view/AgreementView.vue');

var _AgreementView2 = _interopRequireDefault(_AgreementView);

var _indexView = require('./view/indexView.vue');

var _indexView2 = _interopRequireDefault(_indexView);

var _SearchView = require('./view/SearchView.vue');

var _SearchView2 = _interopRequireDefault(_SearchView);

var _ListView = require('./view/ListView.vue');

var _ListView2 = _interopRequireDefault(_ListView);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

console.warn(_index2.default);
_vue2.default.use(_index2.default);
_vue2.default.use(_vueRouter2.default);
_vue2.default.config.debug = true;
var router = new _vueRouter2.default();
_vue2.default.use(_vueTouch2.default);

router.map({
	'/': {
		name: 'index',
		component: _indexView2.default,
		title: '首页'
	},
	'/tab': {
		name: 'tab',
		component: _TabView2.default,
		title: 'tab'
	},
	'/button': {
		name: 'button',
		component: _ButtonView2.default,
		title: 'button'
	},
	'/loading': {
		name: 'loading',
		component: _LoadingView2.default,
		title: 'loading'
	},
	'/toast': {
		name: 'toast',
		component: _ToastView2.default,
		title: 'toast'
	},
	'/share': {
		name: 'share',
		component: _ShareView2.default,
		title: 'share'
	},
	'/line': {
		name: 'line',
		component: _LineView2.default,
		title: 'line'
	},
	'/alert': {
		name: 'alert',
		component: _AlertView2.default,
		title: 'alert'
	},
	'/ad': {
		name: 'ad',
		component: _AdView2.default,
		title: 'ad'
	},
	'/switch': {
		name: 'switch',
		component: _SwitchView2.default,
		title: 'switch'
	},
	'/model': {
		name: 'model',
		component: _ModelView2.default,
		title: 'model'
	},
	'/Mask': {
		name: 'Mask',
		component: _MaskView2.default,
		title: 'Mask'
	},
	'/announcement': {
		name: 'announcement',
		component: _AnnouncementView2.default,
		title: 'announcement'
	},
	'/input': {
		name: 'input',
		component: _InputView2.default,
		title: 'input'
	},
	'/agreement': {
		name: 'agreement',
		component: _AgreementView2.default,
		title: 'agreement'
	},
	'/search': {
		name: 'search',
		component: _SearchView2.default,
		title: 'Seach'
	},
	'/list': {
		name: 'list',
		component: _ListView2.default,
		title: 'list'
	}

});

router.redirect({
	'*': '/'
});
router.start(_App2.default, '#app');


text:
package com.solidnw.gametimer.model;

public class PreferencesConstants {
    /* Preferences */
    public static final String PREFERENCES_NAME = "Preferences";

    public static final String PREF_KEY_THEME = "theme";

    public static final int DEFAULT_THEME = android.R.style.Theme_Holo_Light;
}


text:
echo "Installing Docker"
nix-env -i docker


text:
using Microsoft.Diagnostics.Utilities;
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;

namespace Utilities
{
    /// <summary>
    /// Some applications need to make files that are associated with the application
    /// but also have affinity with other files on the disk.   This class helps manage this
    /// </summary>
    internal static class CacheFiles
    {
        public static float KeepTimeInDays { get; set; }
        public static string CacheDir
        {
            get
            {
                if (s_CacheDir == null)
                {
                    Assembly exeAssembly = Assembly.GetExecutingAssembly();
                    string exePath = exeAssembly.ManifestModule.FullyQualifiedName;
                    string exeName = Path.GetFileNameWithoutExtension(exePath);
                    string tempDir = Environment.GetEnvironmentVariable("TEMP");
                    if (tempDir == null)
                    {
                        tempDir = ".";
                    }

                    s_CacheDir = Path.Combine(tempDir, exeName);

                    string keepTimeEnvVarName = exeName + "_Cache_KeepTimeInDays";
                    string keepTimeEnvVarValueStr = Environment.GetEnvironmentVariable(keepTimeEnvVarName);
                    float keepTimeEnvVarValue;
                    if (keepTimeEnvVarName != null && float.TryParse(keepTimeEnvVarValueStr, out keepTimeEnvVarValue))
                    {
                        // Insure that keep time is at least 10 mins.   This avoids files disappearing while in use.
                        if (keepTimeEnvVarValue < .007f)
                        {
                            keepTimeEnvVarValue = .007f;
                        }

                        KeepTimeInDays = keepTimeEnvVarValue;
                    }
                    else if (KeepTimeInDays == 0)
                    {
                        KeepTimeInDays = 5;
                    }

                    Directory.CreateDirectory(s_CacheDir);
                }
                return s_CacheDir;
            }
            set { s_CacheDir = value; }
        }

        /// <summary>
        /// Find a path name for the file 'baseFilePath' (which can be a path name to anywhere).
        /// which has the extension 'extension'.  It will always return something in 'CacheDir'
        /// and thus might go away.
        /// </summary>
        /// <remarks>
        /// Note that the file 'baseFilePath' is assumed to exist.
        /// </remarks>
        public static string FindFile(string baseFilePath, string extension = "")
        {
            // We expect the original file to exist
            Debug.Assert(File.Exists(baseFilePath));

            var baseFileName = Path.GetFileNameWithoutExtension(baseFilePath);
            var baseFileInfo = new FileInfo(baseFilePath);

            // The hash is a combination of full path, size and last write timestamp
            var hashData = Tuple.Create(Path.GetFullPath(baseFilePath), baseFileInfo.Length, baseFileInfo.LastWriteTimeUtc);
            int hash = hashData.GetHashCode();

            string ret = Path.Combine(CacheDir, baseFileName + "_" + hash.ToString("x") + extension);
            if (File.Exists(ret))
            {
                // See if it is up to date.
                if (File.GetLastWriteTimeUtc(ret) < baseFileInfo.LastWriteTimeUtc)
                {
                    FileUtilities.ForceDelete(ret);
                }
                else
                {
                    // Set the last access time so we can clean up files based on their last usage.
                    // However if someone else is actual using the file, we don't want an 'in use'
                    // exception, so treat this part as optional.
                    try { File.SetLastAccessTimeUtc(ret, DateTime.UtcNow); }
                    catch (Exception) { }
                }
            }
            if (!s_didCleanup)
            {
                s_didCleanup = true;
                Cleanup();
            }
            return ret;
        }
        public static void Cleanup()
        {
            CleanupDirectory(CacheDir, KeepTimeInDays);
        }

        public static void CleanupDirectory(string directory, float keepTimeInDays)
        {
            var nowUTC = DateTime.UtcNow;
            foreach (var file in Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories))
            {
                if ((nowUTC - File.GetLastAccessTimeUtc(file)).TotalDays > keepTimeInDays)
                {
                    try
                    {
                        File.Delete(file);      // Don't try to hard. If it is in use let it be.
                    }
                    catch (Exception) { }
                }
            }
        }

        /// <summary>
        /// Returns true if the output file is up to date with respect to the input file (exists and created after it).
        /// </summary>
        public static bool UpToDate(string outputFile, string inputFile)
        {
            return File.Exists(outputFile) && File.GetLastWriteTimeUtc(inputFile) <= File.GetLastWriteTimeUtc(outputFile);
        }

        #region private
        private static string s_CacheDir;
        private static bool s_didCleanup;
        #endregion
    }
}