text:
package org.jenkinsci.plugins.ghprb;

import antlr.ANTLRException;

import com.coravy.hudson.plugins.github.GithubProjectProperty;
import com.google.common.annotations.VisibleForTesting;

import hudson.Extension;
import hudson.Util;
import hudson.model.*;
import hudson.model.AbstractProject;
import hudson.model.queue.QueueTaskFuture;
import hudson.plugins.git.util.BuildData;
import hudson.triggers.TriggerDescriptor;
import hudson.util.DescribableList;
import hudson.util.FormValidation;
import hudson.util.ListBoxModel;
import hudson.util.ListBoxModel.Option;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.jenkinsci.plugins.ghprb.extensions.GhprbCommitStatus;
import org.jenkinsci.plugins.ghprb.extensions.GhprbExtension;
import org.jenkinsci.plugins.ghprb.extensions.GhprbExtensionDescriptor;
import org.jenkinsci.plugins.ghprb.extensions.comments.GhprbBuildLog;
import org.jenkinsci.plugins.ghprb.extensions.comments.GhprbBuildResultMessage;
import org.jenkinsci.plugins.ghprb.extensions.comments.GhprbBuildStatus;
import org.jenkinsci.plugins.ghprb.extensions.comments.GhprbPublishJenkinsUrl;
import org.jenkinsci.plugins.ghprb.extensions.status.GhprbSimpleStatus;
import org.kohsuke.github.GHCommitState;
import org.kohsuke.github.GitHub;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;

import javax.servlet.ServletException;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;

import jenkins.model.Jenkins;

/**
 * @author Honza Brázdil <jbrazdil@redhat.com>
 */
public class GhprbTrigger extends GhprbTriggerBackwardsCompatible {

    @Extension
    public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
    private static final Logger logger = Logger.getLogger(GhprbTrigger.class.getName());
    private final String adminlist;
    private final Boolean allowMembersOfWhitelistedOrgsAsAdmin;
    private final String orgslist;
    private final String cron;
    private final String buildDescTemplate;
    private final Boolean onlyTriggerPhrase;
    private final Boolean useGitHubHooks;
    private final Boolean permitAll;
    private String whitelist;
    private Boolean autoCloseFailedPullRequests;
    private Boolean displayBuildErrorsOnDownstreamBuilds;
    private List<GhprbBranch> whiteListTargetBranches;
    private transient Ghprb helper;
    private String project;
    private AbstractProject<?, ?> _project;
    private String gitHubAuthId;

    private DescribableList<GhprbExtension, GhprbExtensionDescriptor> extensions = new DescribableList<GhprbExtension, GhprbExtensionDescriptor>(Saveable.NOOP);

    public DescribableList<GhprbExtension, GhprbExtensionDescriptor> getExtensions() {
        if (extensions == null) {
            extensions = new DescribableList<GhprbExtension, GhprbExtensionDescriptor>(Saveable.NOOP,Util.fixNull(extensions));
            extensions.add(new GhprbSimpleStatus());
        }
        return extensions;
    }

    private void setExtensions(List<GhprbExtension> extensions) {
        DescribableList<GhprbExtension, GhprbExtensionDescriptor> rawList = new DescribableList<GhprbExtension, GhprbExtensionDescriptor>(
                Saveable.NOOP,Util.fixNull(extensions));

        // Filter out items that we only want one of, like the status updater.
        this.extensions = Ghprb.onlyOneEntry(rawList,
                                              GhprbCommitStatus.class
                                            );

        // Now make sure we have at least one of the types we need one of.
        Ghprb.addIfMissing(this.extensions, new GhprbSimpleStatus(), GhprbCommitStatus.class);
    }

    @DataBoundConstructor

    public GhprbTrigger(String adminlist,
            String whitelist,
            String orgslist,
            String cron,
            String triggerPhrase,
            Boolean onlyTriggerPhrase,
            Boolean useGitHubHooks,
            Boolean permitAll,
            Boolean autoCloseFailedPullRequests,
            Boolean displayBuildErrorsOnDownstreamBuilds,
            String commentFilePath,
            List<GhprbBranch> whiteListTargetBranches,
            Boolean allowMembersOfWhitelistedOrgsAsAdmin,
            String msgSuccess,
            String msgFailure,
            String commitStatusContext,
            String gitHubAuthId,
            String buildDescTemplate,
            List<GhprbExtension> extensions
            ) throws ANTLRException {
        super(cron);
        this.adminlist = adminlist;
        this.whitelist = whitelist;
        this.orgslist = orgslist;
        this.cron = cron;
        this.triggerPhrase = triggerPhrase;
        this.onlyTriggerPhrase = onlyTriggerPhrase;
        this.useGitHubHooks = useGitHubHooks;
        this.permitAll = permitAll;
        this.autoCloseFailedPullRequests = autoCloseFailedPullRequests;
        this.displayBuildErrorsOnDownstreamBuilds = displayBuildErrorsOnDownstreamBuilds;
        this.whiteListTargetBranches = whiteListTargetBranches;
        this.gitHubAuthId = gitHubAuthId;
        this.allowMembersOfWhitelistedOrgsAsAdmin = allowMembersOfWhitelistedOrgsAsAdmin;
        this.buildDescTemplate = buildDescTemplate;
        setExtensions(extensions);
        configVersion = 1;
    }

    @Override
    public Object readResolve() {
        convertPropertiesToExtensions();
        checkGitHubApiAuth();
        return this;
    }

    @SuppressWarnings("deprecation")
    private void checkGitHubApiAuth() {
        if (gitHubApiAuth != null) {
            gitHubAuthId = gitHubApiAuth.getId();
            gitHubApiAuth = null;
        }
    }

    public static DescriptorImpl getDscp() {
        return DESCRIPTOR;
    }

    @Override
    public void start(AbstractProject<?, ?> project, boolean newInstance) {
        // We should always start the trigger, and handle cases where we don't run in the run function.
        super.start(project, newInstance);
        this._project = project;
        this.project = project.getFullName();

        if (project.isDisabled()) {
            logger.log(Level.FINE, "Project is disabled, not starting trigger for job " + this.project);
            return;
        }
        if (project.getProperty(GithubProjectProperty.class) == null) {
            logger.log(Level.INFO, "GitHub project property is missing the URL, cannot start ghprb trigger for job " + this.project);
            return;
        }
        try {
            helper = createGhprb(project);
        } catch (IllegalStateException ex) {
            logger.log(Level.SEVERE, "Can't start ghprb trigger", ex);
            return;
        }

        logger.log(Level.INFO, "Starting the ghprb trigger for the {0} job; newInstance is {1}",
                new String[] { this.project, String.valueOf(newInstance) });
        helper.init();
    }

    Ghprb createGhprb(AbstractProject<?, ?> project) {
        return new Ghprb(project, this, getDescriptor().getPullRequests(project.getFullName()));
    }

    @Override
    public void stop() {
        logger.log(Level.INFO, "Stopping the ghprb trigger for project {0}", this.project);
        if (helper != null) {
            helper.stop();
            helper = null;
        }
        super.stop();
    }

    @Override
    public void run() {
        // triggers are always triggered on the cron, but we just no-op if we are using GitHub hooks.
        if (getUseGitHubHooks()) {
            logger.log(Level.FINE, "Use webHooks is set, so not running trigger");
            return;
        }

        if ((helper != null && helper.isProjectDisabled()) || (_project != null && _project.isDisabled())) {
            logger.log(Level.FINE, "Project is disabled, ignoring trigger run call for job {0}", this.project);
            return;
        }

        if (helper == null) {
            logger.log(Level.SEVERE, "Helper is null and Project is not disabled, unable to run trigger");
            return;
        }

        logger.log(Level.FINE, "Running trigger for {0}", project);

        helper.run();
        getDescriptor().save();
    }

    public QueueTaskFuture<?> startJob(GhprbCause cause, GhprbRepository repo) {
        ArrayList<ParameterValue> values = getDefaultParameters();
        final String commitSha = cause.isMerged() ? "origin/pr/" + cause.getPullID() + "/merge" : cause.getCommit();
        values.add(new StringParameterValue("sha1", commitSha));
        values.add(new StringParameterValue("ghprbActualCommit", cause.getCommit()));
        String triggerAuthor = "";
        String triggerAuthorEmail = "";
        String triggerAuthorLogin = "";

        try {
            triggerAuthor = getString(cause.getTriggerSender().getName(), "");
        } catch (Exception e) {}
        try {
            triggerAuthorEmail = getString(cause.getTriggerSender().getEmail(), "");
        } catch (Exception e) {}
        try {
            triggerAuthorLogin = getString(cause.getTriggerSender().getLogin(), "");
        } catch (Exception e) {}

        setCommitAuthor(cause, values);

        values.add(new StringParameterValue("ghprbTriggerAuthor", triggerAuthor));
        values.add(new StringParameterValue("ghprbTriggerAuthorEmail", triggerAuthorEmail));
        values.add(new StringParameterValue("ghprbTriggerAuthorLogin", triggerAuthorLogin));
        values.add(new StringParameterValue("ghprbTriggerAuthorLoginMention", !triggerAuthorLogin.isEmpty() ? "@"
                + triggerAuthorLogin : ""));
        final StringParameterValue pullIdPv = new StringParameterValue("ghprbPullId", String.valueOf(cause.getPullID()));
        values.add(pullIdPv);
        values.add(new StringParameterValue("ghprbTargetBranch", String.valueOf(cause.getTargetBranch())));
        values.add(new StringParameterValue("ghprbSourceBranch", String.valueOf(cause.getSourceBranch())));
        values.add(new StringParameterValue("GIT_BRANCH", String.valueOf(cause.getSourceBranch())));
        // it's possible the GHUser doesn't have an associated email address
        values.add(new StringParameterValue("ghprbPullAuthorEmail", getString(cause.getAuthorEmail(), "")));
        values.add(new StringParameterValue("ghprbPullAuthorLogin", String.valueOf(cause.getPullRequestAuthor().getLogin())));
        values.add(new StringParameterValue("ghprbPullAuthorLoginMention", "@" + cause.getPullRequestAuthor().getLogin()));
        values.add(new StringParameterValue("ghprbPullDescription", String.valueOf(cause.getShortDescription())));
        values.add(new StringParameterValue("ghprbPullTitle", String.valueOf(cause.getTitle())));
        values.add(new StringParameterValue("ghprbPullLink", String.valueOf(cause.getUrl())));
        values.add(new StringParameterValue("ghprbPullLongDescription", String.valueOf(cause.getDescription())));
        values.add(new StringParameterValue("ghprbCommentBody", String.valueOf(cause.getCommentBody())));

        // add the previous pr BuildData as an action so that the correct change log is generated by the GitSCM plugin
        // note that this will be removed from the Actions list after the job is completed so that the old (and incorrect)
        // one isn't there
        return this.job.scheduleBuild2(job.getQuietPeriod(), cause, new ParametersAction(values), findPreviousBuildForPullId(pullIdPv));
    }

    public GhprbGitHubAuth getGitHubApiAuth() {
        if (gitHubAuthId == null) {
            for (GhprbGitHubAuth auth: getDescriptor().getGithubAuth()){
                gitHubAuthId = auth.getId();
                getDescriptor().save();
                return auth;
            }
        }
        return getDescriptor().getGitHubAuth(gitHubAuthId);
    }

    public GitHub getGitHub() throws IOException {
        GhprbGitHubAuth auth = getGitHubApiAuth();
        if (auth == null) {
            return null;
        }

        return auth.getConnection(getActualProject());
    }

    public AbstractProject<?, ?> getActualProject() {

        if (_project != null) {
            return _project;
        }

        @SuppressWarnings("rawtypes")
        List<AbstractProject> projects = Jenkins.getInstance().getAllItems(AbstractProject.class);

        for (AbstractProject<?, ?> project : projects) {
            if (project.getFullName().equals(this.project)) {
                return project;
            }
        }
        return null;
    }

    private void setCommitAuthor(GhprbCause cause, ArrayList<ParameterValue> values) {
        String authorName = "";
        String authorEmail = "";
        if (cause.getCommitAuthor() != null) {
            authorName = getString(cause.getCommitAuthor().getName(), "");
            authorEmail = getString(cause.getCommitAuthor().getEmail(), "");
        }

        values.add(new StringParameterValue("ghprbActualCommitAuthor", authorName));
        values.add(new StringParameterValue("ghprbActualCommitAuthorEmail", authorEmail));
    }

    private String getString(String actual, String d) {
        return actual == null ? d : actual;
    }

    /**
     * Find the previous BuildData for the given pull request number; this may return null
     */
    private BuildData findPreviousBuildForPullId(StringParameterValue pullIdPv) {
        // find the previous build for this particular pull request, it may not be the last build
        for (Run<?, ?> r : job.getBuilds()) {
            ParametersAction pa = r.getAction(ParametersAction.class);
            if (pa != null) {
                for (ParameterValue pv : pa.getParameters()) {
                    if (pv.equals(pullIdPv)) {
                        for (BuildData bd : r.getActions(BuildData.class)) {
                            return bd;
                        }
                    }
                }
            }
        }
        return null;
    }

    private ArrayList<ParameterValue> getDefaultParameters() {
        ArrayList<ParameterValue> values = new ArrayList<ParameterValue>();
        ParametersDefinitionProperty pdp = this.job.getProperty(ParametersDefinitionProperty.class);
        if (pdp != null) {
            for (ParameterDefinition pd : pdp.getParameterDefinitions()) {
                if (pd.getName().equals("sha1"))
                    continue;
                values.add(pd.getDefaultParameterValue());
            }
        }
        return values;
    }

    public void addWhitelist(String author) {
        whitelist = whitelist + " " + author;
        try {
            this.job.save();
        } catch (IOException ex) {
            logger.log(Level.SEVERE, "Failed to save new whitelist", ex);
        }
    }

    public String getBuildDescTemplate() {
        return buildDescTemplate == null ? "" : buildDescTemplate;
    }

    public String getAdminlist() {
        if (adminlist == null) {
            return "";
        }
        return adminlist;
    }

    public Boolean getAllowMembersOfWhitelistedOrgsAsAdmin() {
        return allowMembersOfWhitelistedOrgsAsAdmin != null && allowMembersOfWhitelistedOrgsAsAdmin;
    }

    public String getWhitelist() {
        if (whitelist == null) {
            return "";
        }
        return whitelist;
    }

    public String getOrgslist() {
        if (orgslist == null) {
            return "";
        }
        return orgslist;
    }

    public String getCron() {
        return cron;
    }

    public String getProject() {
        return project;
    }

    public String getTriggerPhrase() {
        if (triggerPhrase == null) {
            return "";
        }
        return triggerPhrase;
    }

    public Boolean getOnlyTriggerPhrase() {
        return onlyTriggerPhrase != null && onlyTriggerPhrase;
    }

    public Boolean getUseGitHubHooks() {
        return useGitHubHooks != null && useGitHubHooks;
    }

    public Boolean getPermitAll() {
        return permitAll != null && permitAll;
    }

    public Boolean isAutoCloseFailedPullRequests() {
        if (autoCloseFailedPullRequests == null) {
            Boolean autoClose = getDescriptor().getAutoCloseFailedPullRequests();
            return (autoClose != null && autoClose);
        }
        return autoCloseFailedPullRequests;
    }

    public Boolean isDisplayBuildErrorsOnDownstreamBuilds() {
        if (displayBuildErrorsOnDownstreamBuilds == null) {
            Boolean displayErrors = getDescriptor().getDisplayBuildErrorsOnDownstreamBuilds();
            return (displayErrors != null && displayErrors);
        }
        return displayBuildErrorsOnDownstreamBuilds;
    }

    public List<GhprbBranch> getWhiteListTargetBranches() {
        if (whiteListTargetBranches == null) {
            return new ArrayList<GhprbBranch>();
        }
        return whiteListTargetBranches;
    }

    public GhprbWebHook getWebHook() {
        GhprbWebHook webHook = new GhprbWebHook(this);
        return webHook;
    }

    @Override
    public DescriptorImpl getDescriptor() {
        return DESCRIPTOR;
    }

    @VisibleForTesting
    void setHelper(Ghprb helper) {
        this.helper = helper;
    }

    public GhprbBuilds getBuilds() {
        if (helper == null) {
            logger.log(Level.SEVERE, "The ghprb trigger for {0} wasn''t properly started - helper is null", this.project);
            return null;
        }
        return helper.getBuilds();
    }

    public GhprbRepository getRepository() {
        if (helper == null) {
            logger.log(Level.SEVERE, "The ghprb trigger for {0} wasn''t properly started - helper is null", this.project);
            return null;
        }
        return helper.getRepository();
    }

    public static final class DescriptorImpl extends TriggerDescriptor {
        // GitHub username may only contain alphanumeric characters or dashes and cannot begin with a dash
        private static final Pattern adminlistPattern = Pattern.compile("((\\p{Alnum}[\\p{Alnum}-]*)|\\s)*");

        private Integer configVersion;

        /**
         * These settings only really affect testing. When Jenkins calls configure() then the formdata will
         * be used to replace all of these fields. Leaving them here is useful for
         * testing, but must not be confused with a default. They also should not be used as the default
         * value in the global.jelly file as this value is dynamic and will not be
         * retained once configure() is called.
         */
        private String whitelistPhrase = ".*add\\W+to\\W+whitelist.*";
        private String okToTestPhrase = ".*ok\\W+to\\W+test.*";
        private String retestPhrase = ".*test\\W+this\\W+please.*";
        private String skipBuildPhrase = ".*\\[skip\\W+ci\\].*";
        private String cron = "H/5 * * * *";
        private Boolean useComments = false;
        private Boolean useDetailedComments = false;
        private GHCommitState unstableAs = GHCommitState.FAILURE;
        private List<GhprbBranch> whiteListTargetBranches;
        private Boolean autoCloseFailedPullRequests = false;
        private Boolean displayBuildErrorsOnDownstreamBuilds = false;

        private List<GhprbGitHubAuth> githubAuth;

        public GhprbGitHubAuth getGitHubAuth(String gitHubAuthId) {

            if (gitHubAuthId == null) {
                return getGithubAuth().get(0);
            }

            GhprbGitHubAuth firstAuth = null;
            for (GhprbGitHubAuth auth : getGithubAuth()) {
                if (firstAuth == null) {
                    firstAuth = auth;
                }
                if (auth.getId().equals(gitHubAuthId)) {
                    return auth;
                }
            }
            return firstAuth;
        }

        public List<GhprbGitHubAuth> getGithubAuth() {
            if (githubAuth == null || githubAuth.size() == 0) {
                githubAuth = new ArrayList<GhprbGitHubAuth>(1);
                githubAuth.add(new GhprbGitHubAuth(null, null, "Anonymous connection", null, null));
            }
            return githubAuth;
        }

        public List<GhprbGitHubAuth> getDefaultAuth(List<GhprbGitHubAuth> githubAuth) {
            if (githubAuth != null && githubAuth.size() > 0) {
                return githubAuth;
            }
            return getGithubAuth();
        }

        private String adminlist;

        private String requestForTestingPhrase;

        // map of jobs (by their fullName) and their map of pull requests
        private Map<String, ConcurrentMap<Integer, GhprbPullRequest>> jobs;

        public List<GhprbExtensionDescriptor> getExtensionDescriptors() {
            return GhprbExtensionDescriptor.allProject();
        }

        public List<GhprbExtensionDescriptor> getGlobalExtensionDescriptors() {
            return GhprbExtensionDescriptor.allGlobal();
        }

        private DescribableList<GhprbExtension, GhprbExtensionDescriptor> extensions;

        public DescribableList<GhprbExtension, GhprbExtensionDescriptor> getExtensions() {
            if (extensions == null) {
                extensions = new DescribableList<GhprbExtension, GhprbExtensionDescriptor>(Saveable.NOOP);
            }
            return extensions;
        }

        public DescriptorImpl() {
            load();
            readBackFromLegacy();
            if (jobs == null) {
                jobs = new HashMap<String, ConcurrentMap<Integer, GhprbPullRequest>>();
            }
//            save();
        }

        @Override
        public boolean isApplicable(Item item) {
            return true;
        }

        @Override
        public String getDisplayName() {
            return "GitHub Pull Request Builder";
        }

        @Override
        public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
            adminlist = formData.getString("adminlist");
            requestForTestingPhrase = formData.getString("requestForTestingPhrase");
            whitelistPhrase = formData.getString("whitelistPhrase");
            okToTestPhrase = formData.getString("okToTestPhrase");
            retestPhrase = formData.getString("retestPhrase");
            skipBuildPhrase = formData.getString("skipBuildPhrase");
            cron = formData.getString("cron");
            useComments = formData.getBoolean("useComments");
            useDetailedComments = formData.getBoolean("useDetailedComments");
            unstableAs = GHCommitState.valueOf(formData.getString("unstableAs"));
            autoCloseFailedPullRequests = formData.getBoolean("autoCloseFailedPullRequests");
            displayBuildErrorsOnDownstreamBuilds = formData.getBoolean("displayBuildErrorsOnDownstreamBuilds");

            githubAuth = req.bindJSONToList(GhprbGitHubAuth.class, formData.get("githubAuth"));

            extensions = new DescribableList<GhprbExtension, GhprbExtensionDescriptor>(Saveable.NOOP);

            try {
                extensions.rebuildHetero(req, formData, getGlobalExtensionDescriptors(), "extensions");
            } catch (IOException e) {
                e.printStackTrace();
            }

            readBackFromLegacy();

            save();
            return super.configure(req, formData);
        }

        public FormValidation doCheckAdminlist(@QueryParameter String value) throws ServletException {
            if (!adminlistPattern.matcher(value).matches()) {
                return FormValidation.error("GitHub username may only contain alphanumeric characters or dashes "
                        + "and cannot begin with a dash. Separate them with whitespaces.");
            }
            return FormValidation.ok();
        }

        public ListBoxModel doFillUnstableAsItems() {
            ListBoxModel items = new ListBoxModel();
            GHCommitState[] results = new GHCommitState[] {GHCommitState.SUCCESS,GHCommitState.ERROR,GHCommitState.FAILURE};
            for (GHCommitState nextResult : results) {
                String text = StringUtils.capitalize(nextResult.toString().toLowerCase());
                items.add(text, nextResult.toString());
                if (unstableAs.toString().equals(nextResult)) {
                    items.get(items.size()-1).selected = true;
                }
            }

            return items;
        }

        public String getAdminlist() {
            return adminlist;
        }

        public String getRequestForTestingPhrase() {
            return requestForTestingPhrase;
        }

        public String getWhitelistPhrase() {
            return whitelistPhrase;
        }

        public String getOkToTestPhrase() {
            return okToTestPhrase;
        }

        public String getRetestPhrase() {
            return retestPhrase;
        }

        public String getSkipBuildPhrase() {
            return skipBuildPhrase;
        }

        public String getCron() {
            return cron;
        }

        public Boolean getUseComments() {
            return useComments;
        }

        public Boolean getUseDetailedComments() {
            return useDetailedComments;
        }

        public Boolean getAutoCloseFailedPullRequests() {
            return autoCloseFailedPullRequests;
        }

        public Boolean getDisplayBuildErrorsOnDownstreamBuilds() {
            return displayBuildErrorsOnDownstreamBuilds;
        }

        public GHCommitState getUnstableAs() {
            return unstableAs;
        }

        public boolean isUseComments() {
            return (useComments != null && useComments);
        }

        public boolean isUseDetailedComments() {
            return (useDetailedComments != null && useDetailedComments);
        }

        public ListBoxModel doFillGitHubAuthIdItems(@QueryParameter("gitHubAuthId") String gitHubAuthId) {
            ListBoxModel model = new ListBoxModel();
            for (GhprbGitHubAuth auth : getGithubAuth()) {
                String description = Util.fixNull(auth.getDescription());
                int length = description.length();
                length = length > 50 ? 50 : length;
                Option next = new Option(auth.getServerAPIUrl() + " : " + description.substring(0, length), auth.getId());
                if (!StringUtils.isEmpty(gitHubAuthId) && gitHubAuthId.equals(auth.getId())) {
                    next.selected = true;
                }
                model.add(next);
            }
            return model;
        }

        public ConcurrentMap<Integer, GhprbPullRequest> getPullRequests(String projectName) {
            ConcurrentMap<Integer, GhprbPullRequest> ret;
            if (jobs.containsKey(projectName)) {
                Map<Integer, GhprbPullRequest> map = jobs.get(projectName);
                if (!(map instanceof ConcurrentMap)) {
                    map = new ConcurrentHashMap<Integer, GhprbPullRequest>(map);
                }
                jobs.put(projectName, (ConcurrentMap<Integer, GhprbPullRequest>) map);
                ret = (ConcurrentMap<Integer, GhprbPullRequest>) map;
            } else {
                ret = new ConcurrentHashMap<Integer, GhprbPullRequest>();
                jobs.put(projectName, ret);
            }
            return ret;
        }

        public List<GhprbBranch> getWhiteListTargetBranches() {
            return whiteListTargetBranches;
        }

        @Deprecated
        private transient String publishedURL;
        @Deprecated
        private transient Integer logExcerptLines;
        @Deprecated
        private transient String msgSuccess;
        @Deprecated
        private transient String msgFailure;
        @Deprecated
        private transient String commitStatusContext;
        @Deprecated
        private transient String accessToken;
        @Deprecated
        private transient String username;
        @Deprecated
        private transient String password;
        @Deprecated
        private transient String serverAPIUrl;

        public void readBackFromLegacy() {
            if (configVersion == null) {
                configVersion = 0;
            }

            if (logExcerptLines != null && logExcerptLines > 0) {
                addIfMissing(new GhprbBuildLog(logExcerptLines));
                logExcerptLines = null;
            }
            if (!StringUtils.isEmpty(publishedURL)) {
                addIfMissing(new GhprbPublishJenkinsUrl(publishedURL));
                publishedURL = null;
            }
            if (!StringUtils.isEmpty(msgFailure) || !StringUtils.isEmpty(msgSuccess)) {
                List<GhprbBuildResultMessage> messages = new ArrayList<GhprbBuildResultMessage>(2);
                if (!StringUtils.isEmpty(msgFailure)) {
                    messages.add(new GhprbBuildResultMessage(GHCommitState.FAILURE, msgFailure));
                    msgFailure = null;
                }
                if (!StringUtils.isEmpty(msgSuccess)) {
                    messages.add(new GhprbBuildResultMessage(GHCommitState.SUCCESS, msgSuccess));
                    msgSuccess = null;
                }
                addIfMissing(new GhprbBuildStatus(messages));
            }

            if (configVersion < 1) {
                GhprbSimpleStatus status = new GhprbSimpleStatus(commitStatusContext);
                addIfMissing(status);
                commitStatusContext = null;
            }

            if (!StringUtils.isEmpty(accessToken)) {
                try {
                    GhprbGitHubAuth auth = new GhprbGitHubAuth(serverAPIUrl, Ghprb.createCredentials(serverAPIUrl, accessToken), "Pre credentials Token", null, null);
                    if (githubAuth == null) {
                        githubAuth = new ArrayList<GhprbGitHubAuth>(1);
                    }
                    githubAuth.add(auth);
                    accessToken = null;
                    serverAPIUrl = null;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            if (!StringUtils.isEmpty(username) || !StringUtils.isEmpty(password)) {
                try {
                    GhprbGitHubAuth auth = new GhprbGitHubAuth(serverAPIUrl, Ghprb.createCredentials(serverAPIUrl, username, password), "Pre credentials username and password", null, null);
                    if (githubAuth == null) {
                        githubAuth = new ArrayList<GhprbGitHubAuth>(1);
                    }
                    githubAuth.add(auth);
                    username = null;
                    password = null;
                    serverAPIUrl = null;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            configVersion = 1;
        }

        private void addIfMissing(GhprbExtension ext) {
            if (getExtensions().get(ext.getClass()) == null) {
                getExtensions().add(ext);
            }
        }

    }

}


text:
@interface JPRootViewController ()

@end

@implementation JPRootViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];

    [JPEngine startEngine];

#if TARGET_IPHONE_SIMULATOR
    //playground调试
    //JS测试包的本地绝对路径
    NSString *rootPath = @"/Users/Awhisper/Desktop/Github/JSPatch/Demo/iOSPlaygroundToolDemo/JSPatchPlaygroundDemo";

    NSString *scriptRootPath = [rootPath stringByAppendingPathComponent:@"js"];
    NSString *mainScriptPath = [NSString stringWithFormat:@"%@/%@", scriptRootPath, @"demo.js"];
    [JPPlayground setReloadCompleteHandler:^{
        [self showController];
    }];
    [JPPlayground startPlaygroundWithJSPath:mainScriptPath];

#else
    //正常执行JSPatch
    NSString *rootPath = [[NSBundle mainBundle] bundlePath];

    NSString *scriptPath = [rootPath stringByAppendingPathComponent:@"demo.js"];
    NSString *script = [NSString stringWithContentsOfFile:scriptPath encoding:NSUTF8StringEncoding error:nil];
    [JPEngine evaluateScript:script];
#endif

    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, 50)];
    [btn setTitle:@"Push Playground" forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(showController) forControlEvents:UIControlEventTouchUpInside];
    [btn setBackgroundColor:[UIColor grayColor]];
    [self.view addSubview:btn];
}

- (void)showController
{
    Class clz = NSClassFromString(@"JPDemoController");
    id vc = [[clz alloc]init];
    [self.navigationController pushViewController:vc animated:NO];
}

@end

redpajama_set_name: RedPajamaGithub


text:
ACCEPTED

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
Sapr. Unit. Stat. 125 (1892)

#### Original name
Achlya papillosa Humphrey, 1892

### Remarks
null


text:
package avantssar.aslanpp.library;

import org.avantssar.aslan.IASLanSpec;
import org.avantssar.commons.ChannelEntry;
import org.avantssar.commons.ChannelModel;
import org.avantssar.commons.ChannelEntry.Type;
import avantssar.aslanpp.testing.IChannelTypeFlexibleSpecProvider;

public abstract class AbstractChannelledSpecProvider extends AbstractSpecProvider implements IChannelTypeFlexibleSpecProvider {

	protected ChannelEntry channelType = ChannelEntry.regular;

	@Override
	public void setChannelType(ChannelEntry channelType) {
		this.channelType = channelType;
	}

	public ChannelEntry getChannelType() {
		return channelType;
	}

	private org.avantssar.aslan.ITerm receiveCCM(org.avantssar.aslan.ITerm receiver, org.avantssar.aslan.ITerm sender, org.avantssar.aslan.ITerm pseudo, org.avantssar.aslan.ITerm payload) {
		return sendCCM(sender, pseudo, receiver, payload);
	}

	private org.avantssar.aslan.ITerm sendCCM(org.avantssar.aslan.ITerm sender, org.avantssar.aslan.ITerm pseudo, org.avantssar.aslan.ITerm receiver, org.avantssar.aslan.ITerm payload) {
		if (pseudo.getRepresentation().equals(sender.getRepresentation())) {
			if (channelType.type == Type.Confidential) {
				return IASLanSpec.IKNOWS.term(IASLanSpec.CRYPT.term(fCK.term(receiver), IASLanSpec.PAIR.term(ccmConf.term(), payload)));
			}
			else if (channelType.type == Type.Secure) {
				return IASLanSpec.IKNOWS.term(IASLanSpec.CRYPT.term(fCK.term(receiver), IASLanSpec.SIGN.term(IASLanSpec.INV.term(fAK.term(pseudo)), IASLanSpec.PAIR.term(ccmSec.term(), IASLanSpec.PAIR
						.term(receiver, payload)))));
			}
			else if (channelType.type == Type.Authentic) {
				return IASLanSpec.IKNOWS.term(IASLanSpec.SIGN.term(IASLanSpec.INV.term(fAK.term(pseudo)), IASLanSpec.PAIR.term(ccmAuth.term(), IASLanSpec.PAIR.term(receiver, payload))));
			}
			else {
				return IASLanSpec.IKNOWS.term(payload);
			}
		}
		else {
			if (channelType.type == Type.Confidential) {
				return IASLanSpec.IKNOWS.term(IASLanSpec.CRYPT.term(fPK.term(receiver), IASLanSpec.PAIR.term(ccmConf.term(), payload)));
			}
			else if (channelType.type == Type.Secure) {
				return IASLanSpec.IKNOWS.term(IASLanSpec.PAIR.term(pseudo, IASLanSpec.CRYPT.term(fPK.term(receiver), IASLanSpec.SIGN.term(IASLanSpec.INV.term(pseudo), IASLanSpec.PAIR.term(ccmSec
						.term(), IASLanSpec.PAIR.term(receiver, payload))))));
			}
			else if (channelType.type == Type.Authentic) {
				return IASLanSpec.IKNOWS.term(IASLanSpec.PAIR.term(pseudo, IASLanSpec.SIGN.term(IASLanSpec.INV.term(pseudo), IASLanSpec.PAIR.term(ccmAuth.term(), IASLanSpec.PAIR.term(receiver,
						payload)))));
			}
			else {
				return IASLanSpec.IKNOWS.term(payload);
			}
		}
	}

	protected org.avantssar.aslan.ITerm doSend(ChannelModel cm, org.avantssar.aslan.ITerm sender, org.avantssar.aslan.ITerm pseudo, org.avantssar.aslan.ITerm receiver,
			org.avantssar.aslan.ITerm payload) {
		return doSend(cm, sender, pseudo, receiver, payload, null);
	}

	protected org.avantssar.aslan.ITerm doSend(ChannelModel cm, org.avantssar.aslan.ITerm sender, org.avantssar.aslan.ITerm pseudo, org.avantssar.aslan.ITerm receiver,
			org.avantssar.aslan.ITerm payload, org.avantssar.aslan.ITerm channel) {
		if (cm == ChannelModel.ACM) {
			return sendACM(sender, pseudo, receiver, payload, channel);
		}
		else if (cm == ChannelModel.CCM) {
			return sendCCM(sender, pseudo, receiver, payload);
		}
		else {
			return null;
		}
	}

	protected org.avantssar.aslan.ITerm doReceive(ChannelModel cm, org.avantssar.aslan.ITerm receiver, org.avantssar.aslan.ITerm sender, org.avantssar.aslan.ITerm pseudo,
			org.avantssar.aslan.ITerm payload) {
		return doReceive(cm, receiver, sender, pseudo, payload, null);
	}

	protected org.avantssar.aslan.ITerm doReceive(ChannelModel cm, org.avantssar.aslan.ITerm receiver, org.avantssar.aslan.ITerm sender, org.avantssar.aslan.ITerm pseudo,
			org.avantssar.aslan.ITerm payload, org.avantssar.aslan.ITerm channel) {
		if (cm == ChannelModel.ACM) {
			return receiveACM(receiver, pseudo, payload, channel);
		}
		else if (cm == ChannelModel.CCM) {
			return receiveCCM(receiver, sender, pseudo, payload);
		}
		else {
			return null;
		}

	}

	private org.avantssar.aslan.ITerm sendACM(org.avantssar.aslan.ITerm sender, org.avantssar.aslan.ITerm pseudo, org.avantssar.aslan.ITerm receiver, org.avantssar.aslan.ITerm payload,
			org.avantssar.aslan.ITerm channel) {
		org.avantssar.aslan.ITerm finalChannel;
		if (channel != null) {
			finalChannel = channel;
		}
		else {
			org.avantssar.aslan.Constant chtype = acmChannelType();
			finalChannel = acmChFnc.term(pseudo, receiver, chtype.term());
		}
		return acmSent.term(sender, pseudo, receiver, payload, finalChannel);
	}

	private org.avantssar.aslan.ITerm receiveACM(org.avantssar.aslan.ITerm receiver, org.avantssar.aslan.ITerm pseudo, org.avantssar.aslan.ITerm payload, org.avantssar.aslan.ITerm channel) {
		org.avantssar.aslan.ITerm finalChannel;
		if (channel != null) {
			finalChannel = channel;
		}
		else {
			org.avantssar.aslan.Constant chtype = acmChannelType();
			finalChannel = acmChFnc.term(pseudo, receiver, chtype.term());
		}
		return acmRcvd.term(receiver, pseudo, payload, finalChannel);
	}

	private org.avantssar.aslan.Constant acmChannelType() {
		if (channelType.type == Type.Authentic) {
			return cACM_auth;
		}
		else if (channelType.type == Type.Secure) {
			return cACM_sec;
		}
		else if (channelType.type == Type.Confidential) {
			return cACM_conf;
		}
		else {
			return cACM_regular;
		}
	}
}


text:
package org.eclipse.microprofile.metrics.tck.metrics;

import org.eclipse.microprofile.metrics.tck.util.ControlledInvocation;
import org.eclipse.microprofile.metrics.tck.util.BeanWithControlledInvocation;
import org.eclipse.microprofile.metrics.tck.util.TimeUtil;
import org.eclipse.microprofile.metrics.MetricID;
import org.eclipse.microprofile.metrics.MetricRegistry;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.junit.InSequence;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Test;
import org.junit.runner.RunWith;

import javax.inject.Inject;
import java.util.concurrent.TimeoutException;

import static org.junit.Assert.assertEquals;

@RunWith(Arquillian.class)
public class ConcurrentGaugeFunctionalTest {

    @Deployment
    static Archive<?> createTestArchive() {
        return ShrinkWrap.create(JavaArchive.class)
            .addClass(ConcurrentGaugeFunctionalTest.class)
            .addClass(ConcurrentGaugeFunctionalBean.class)
            .addClass(BeanWithControlledInvocation.class)
            .addClass(ControlledInvocation.class)
            .addClass(TimeUtil.class)
            .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
    }

    @Inject
    private MetricRegistry metricRegistry;

    @Inject
    private ConcurrentGaugeFunctionalBean bean;

    static final int NUMBER_OF_INVOCATIONS = 20;

    /**
     * To test the 'min' and 'max' values we have to do this:
     * - run invocation1 and keep it running
     * - wait until the next minute starts
     * - run invocation2 and stop it right away
     * - wait until the next minute starts
     * - stop invocation1
     * - after this, 'min' should be 1 and 'max' should be 2
     */
    @Test
    @InSequence(1)
    public void testMinMax() throws TimeoutException, InterruptedException {
        ControlledInvocation invocation1 = new ControlledInvocation(bean);
        ControlledInvocation invocation2 =  new ControlledInvocation(bean);
        invocation1.start();
        try {
            TimeUtil.waitForNextMinute();
            invocation2 = new ControlledInvocation(bean);
            invocation2.start();
            invocation2.stop();
            TimeUtil.waitForNextMinute();
            invocation1.stop();
            assertEquals("Minimum should be 1 ", 1,
                metricRegistry.getConcurrentGauges().get(new MetricID("mygauge")).getMin());
            assertEquals("Maximum should be 2", 2,
                metricRegistry.getConcurrentGauges().get(new MetricID("mygauge")).getMax());
        }
        finally {
            invocation1.stop();
            invocation2.stop();
        }
    }

    /**
     * Over time, run multiple invocations on the bean (so that at one point, all are running at the same time).
     * Over time, check that the concurrent gauge's value is updated properly.
     * After that, start stopping the invocations one by one, and again, check that the concurrent gauge is updated.
     */
    @Test
    @InSequence(2)
    public void testConcurrentInvocations() throws InterruptedException, TimeoutException {
        ControlledInvocation[] invocations = new ControlledInvocation[NUMBER_OF_INVOCATIONS];
        try {
            // run some clients for the first method, see the 'count' of the concurrent gauge increment over time
            for (int i = 0; i < NUMBER_OF_INVOCATIONS; i++) {
                invocations[i] = new ControlledInvocation(bean);
                invocations[i].start();
                assertEquals(i + 1,
                    metricRegistry.getConcurrentGauges().get(new MetricID("mygauge")).getCount());
            }
            // stop all clients and see the 'count' of the concurrent gauge decrement over time
            for (int i = 0; i < NUMBER_OF_INVOCATIONS; i++) {
                invocations[i].stop();
                assertEquals(NUMBER_OF_INVOCATIONS - i - 1,
                    metricRegistry.getConcurrentGauges().get(new MetricID("mygauge")).getCount());
            }
        }
        finally {
            try {
                for(ControlledInvocation invocation : invocations) {
                    invocation.stop();
                }
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}


text: makeit clean release


text:
![Hex](https://raw.githubusercontent.com/3lvis/Hex/master/Images/hex.png)

>A hex triplet is a six-digit, three-byte hexadecimal number used in HTML, CSS, SVG, and other computing applications to represent colors. The bytes represent the red, green and blue components of the color. One byte represents a number in the range 00 to FF (in hexadecimal notation), or 0 to 255 in decimal notation. This represents the least (0) to the most (255) intensity of each of the color components. Thus web colors specify colors in the True Color (24-bit RGB) color scheme.

Dealing with HEX colors in iOS is problematic and can become quite repetitive, we've long waited for Apple to do something about this but nothing has really happened.

This is why I created `Hex`, a simple tiny extension to UIColor that helps you in this case. It works nicely with both Objective-C and Swift.

## Installation

```ruby
pod 'Hex'
```

## Create color

### Swift
``` swift
import Hex

let redColor = UIColor(hex: "FF0000")
```

### Objective-C

```objc
@import Hex;

UIColor *color = [[UIColor alloc] initWithHex:@"FF0000"];
```

## Translucency

`HEX` doesn't support translucency, since it's only RGB, but we thought why it shouldn't? That's why you can append the translucency percentage at the end of your HEX string.

Some examples:

```swift
UIColor(hex: "#ff0000")   => UIColor.redColor()
UIColor(hex: "#ff000075") => UIColor.redColor().colorWithAlphaComponent(0.75)
UIColor(hex: "#ff000050") => UIColor.redColor().colorWithAlphaComponent(0.50)
```

## Check for equal colors

Using `isEqual` on UIColor doesn't work when you create the color from an `HEX` string, this is because how UIKit handles colors. That's why before comparing a color you have to convert the colors to RGBSpace. Luckly `Hex` contains a helper method that helps you  checking for equal colors, internally this method normalizes the color space of colors.

```swift
let blackHex = UIColor(hex: "000000")
let black = UIColor.blackColor()

if blackHex.isEqualTo(black) {
    // Do something
}
```

```objc
UIColor *blackHex = [[UIColor alloc] initWithHex: @"000000"];
UIColor *black = [UIColor blackColor];

if ([blackHex isEqualTo:black]) {
    // Do something
}
```

## Be Awesome

If something looks stupid, please create a friendly and constructive issue, getting your feedback would be awesome.

Have a great day.

## Author

Elvis Nuñez, [@3lvis](https://twitter.com/3lvis)

## License

**Hex** is available under the MIT license. See the [LICENSE](/LICENSE.md) file for more info.


text:
jqCore.prototype.append = function (node) {
    var firstElement = this.get(0);
    firstElement.addChild(node);
    return this
}
jqCore.prototype.prepend = function (node) {
    var firstElement = this.get(0);
    firstElement.addChild(node,0);
    return this
}

jqCore.prototype.after =jqCore.prototype.before= function (node) {
    var firstElement = this.get(0);
    var parent = firstElement.getParent();
    if (parent) {
        parent.addChild(node);
    }
    return this

}

jqCore.prototype.empty = function () {
    this.each(function (n, i) {
        i.removeAllChildren();
    });
}

jqCore.prototype.remove = function () {
    this.each(function (n, i) {
        i.removeFromParent();
    });
}


text:
import Ember from 'ember';
import layout from '../templates/components/physical-object';

export default Ember.Component.extend({
  layout,
  tagName: '',
  didInsertElement() {
    let world = this.get('in');
    if (!world) {
      throw new Error('physical-object must be placed inside a world');
    }
    world.addObject(this);
  },
  willDestroyElement() {
    let world = this.get('in');
    world.removeObject(this);
  },
  place(tracker) {
    if (!this.isDestroyed) {
      this.set('tracker', tracker);
    }
  }
});


text:
/**
 *
 */
package com.rocket.tms.service;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javapns.Push;
import javapns.communication.exceptions.CommunicationException;
import javapns.communication.exceptions.KeystoreException;
import net.trubiquity.tpa.identity.admin.impl.CommunityAdministrationStub;
import net.trubiquity.tpa.identity.admin.impl.ProfileAdministrationStub;
import net.trubiquity.tpa.identity.impl.IdentityResolverStub;
import net.trubiquity.tpa.identity.impl.IdentityStub;
import net.trubiquity.tpa.identity.impl.KeyData;
import net.trubiquity.tpa.identity.impl.KeyType;
import net.trubiquity.tpa.identity.impl.PasswordCredentials;
import net.trubiquity.tpa.identity.impl.SimpleIdentityToken;
import net.trubiquity.tpa.identity.impl.TRUCoreKeyStore;
import net.trubiquity.tpa.objects.identity.IIdentityToken;
import net.trubiquity.tpa.objects.identity.IMembershipGroupHandle;
import net.trubiquity.tpa.objects.identity.IUser;
import net.trubiquity.tpa.objects.identity.admin.ICommunity.CommunityEncryptionType;
import net.trubiquity.tpa.objects.identity.admin.impl.Community;
import net.trubiquity.tpa.objects.identity.admin.impl.CommunityHandle;
import net.trubiquity.tpa.objects.identity.admin.impl.UserProfile;
import net.trubiquity.tpa.objects.identity.impl.User;
import net.trubiquity.tpa.objects.pkg.IMetaDataList;
import net.trubiquity.tpa.objects.pkg.IPackageList;
import net.trubiquity.tpa.pkg.impl.PackageFilter;
import net.trubiquity.tpa.pkg.impl.PackageHandle;
import net.trubiquity.tpa.pkg.impl.PackageList;
import net.trubiquity.tpa.pkg.impl.PackagePayload;
import net.trubiquity.tpa.pkg.impl.TPAPackage;
import net.trubiquity.tpa.router.ServiceException;
import net.trubiquity.tpa.trushare.impl.TRUShareSimpleClient;

import org.json.JSONException;
import org.springframework.stereotype.Service;

import com.rocket.tms.json.ReqGetDownloadFilsJsonObj;
import com.rocket.tms.json.ReqGetPartnersJsonObj;
import com.rocket.tms.json.ReqLoginJsonObj;
import com.rocket.tms.json.ResFileUploadJsonObj;
import com.rocket.tms.json.RespDownloadFileJsonObj;
import com.rocket.tms.json.RespGetDownloadFilesJsonObj;
import com.rocket.tms.json.RespGetPartnerJsonObj;
import com.rocket.tms.json.RespLoginJsonObj;
import com.rocket.tms.json.RespPartner;
import com.rocket.tms.json.ResponseJsonObj;
import com.rocket.tms.util.Constant;
import com.rocket.tms.util.JsonHelper;
import com.rocket.tpa.mfx.DataExchangeProgressEventArgs;
import com.rocket.tpa.mfx.IMFXClient;
import com.rocket.tpa.mfx.MFXActionListener;
import com.rocket.tpa.mfx.MFXClient;
import com.rocket.tpa.mfx.PackageDetails;
import com.rocket.tpa.mfx.PackageFilterType;

/**
 * @author xxu
 *
 */
@Service
public class TrucoreMSServiceImpl implements TrucoreMSService {

	public static HashMap<String, SimpleIdentityToken> tokenMap = new HashMap<String, SimpleIdentityToken>();
	private CommunityAdministrationStub mCommunityAdministrationStub = new CommunityAdministrationStub(Constant.COMMUNITY_BASE_URL);
	private TRUShareSimpleClient mTRUShareSimpleClient = new TRUShareSimpleClient(Constant.TRUSHARE_IDENTITY_URL, Constant.TRUSHARE_BASE_URL);
	private IdentityResolverStub mIdentityResolverStub = new IdentityResolverStub(Constant.IDENTITY_BASE_URL);
	private ProfileAdministrationStub mProfileAdministrationStub = new ProfileAdministrationStub(Constant.PROFILE_BASE_URL);
	private TRUCoreKeyStore keyStore = new TRUCoreKeyStore(Constant.TRUCORE_STORE_BASE_URL);
	private static String IOStoken = "4884adef5c5dfbb51f4f51807a84d83ae08ac95032c0559dac8b285a49453392";

	/**
	 * IMFXClient is used for file transfer to TRUCore server MFXActionListener
	 * is a handler for get proccess status when file transfer , you can
	 * implement yourself's logic on every status.
	 */
	private IMFXClient MFXClient = new MFXClient(Constant.MFX_BASE_URL, new MFXActionListener() {

		@Override
		public void onProgressChanged(DataExchangeProgressEventArgs e) {
			switch (e.Action) {
			case Downloading:
				break;
			case DownloadCompleted:
				break;
			case Decrypting:
				break;
			case DecryptionCompleted:
				break;
			case Encrypting:
				break;
			case EncryptionCompleted:
				break;
			case UploadCompleted:
				break;
			case Uploading:
				String msg = "You receive a new file notification.";
				System.out.println(msg);
				pushNotificationsToiOSdevices(msg);
				break;
			default:
				break;
			}

		}

	}, mIdentityResolverStub, mCommunityAdministrationStub, mTRUShareSimpleClient, mProfileAdministrationStub, keyStore);

	@Override
	public ResponseJsonObj login(String jsonString) {
		RespLoginJsonObj respLoginJsonObj = new RespLoginJsonObj();
		try {
			ReqLoginJsonObj loginJson = JsonHelper.parseObject(jsonString, ReqLoginJsonObj.class);
			IdentityStub mIdentityStub = new IdentityStub(Constant.IDENTITY_STUB_URL);
			if (loginJson.username == null || loginJson.username.equals("")) {
				respLoginJsonObj.result = TrucoreMSService.FAILED;
				respLoginJsonObj.log = "User name is null";
			}

			else if (loginJson.password == null || loginJson.password.equals("")) {
				respLoginJsonObj.result = TrucoreMSService.FAILED;
				respLoginJsonObj.log = "Password is null";
			} else {
				PasswordCredentials credentials = new PasswordCredentials(loginJson.username, loginJson.password);
				SimpleIdentityToken token = (SimpleIdentityToken) mIdentityStub.login(credentials);
				respLoginJsonObj.result = SUCCESS;
				respLoginJsonObj.token = token.getAuthenticationToken();
//				tokenMap.clear();
				tokenMap.put(token.getAuthenticationToken(), token);
			}

		} catch (JSONException e) {
			respLoginJsonObj.result = TrucoreMSService.FAILED;
			respLoginJsonObj.log = e.getMessage();
			e.printStackTrace();
		} catch (ServiceException e) {
			respLoginJsonObj.result = TrucoreMSService.FAILED;
			respLoginJsonObj.log = e.getMessage();
			e.printStackTrace();
		}
		return respLoginJsonObj;
	}

	@Override
	public ResponseJsonObj getPartners(String jsonString) {
		RespGetPartnerJsonObj respGetPartnerJsonObj = new RespGetPartnerJsonObj();
		try {
			ReqGetPartnersJsonObj getPartnersJsonObj = JsonHelper.parseObject(jsonString, ReqGetPartnersJsonObj.class);
			SimpleIdentityToken token = tokenMap.get(getPartnersJsonObj.token);
			List<IUser> tp = null;
			ProfileAdministrationStub mProfileAdministrationStub = new ProfileAdministrationStub(Constant.PROFILE_BASE_URL);
			CommunityAdministrationStub mCommunityAdministrationStub = new CommunityAdministrationStub(Constant.COMMUNITY_BASE_URL);
			TRUShareSimpleClient mTRUShareSimpleClient = new TRUShareSimpleClient(Constant.TRUSHARE_IDENTITY_URL, Constant.TRUSHARE_BASE_URL);
			UserProfile myProfile = (UserProfile) mProfileAdministrationStub.getMyProfile(token);
			// Get community
			List<IMembershipGroupHandle> lsCommunities = mCommunityAdministrationStub.getCommunitiesOfUser(token, myProfile);
			Community community = (Community) lsCommunities.get(0);
			tp = mTRUShareSimpleClient.findPartners(token, community.getCommunityUniqueID(), "", "", "", "", "", "", "", "", "", 0, 200);
			for (IUser iuser : tp) {
				User user = (User) iuser;
				RespPartner partner = new RespPartner();
				partner.username = user.getUsername();
				partner.company = user.getCompanyName();
				partner.firstname = user.getFirstName();
				partner.lastname = user.getLastName();
				partner.email = user.getEmail();
				respGetPartnerJsonObj.partners.add(partner);
			}
			respGetPartnerJsonObj.result = SUCCESS;
		} catch (Exception e) {
			respGetPartnerJsonObj.result = TrucoreMSService.FAILED;
			respGetPartnerJsonObj.log = e.getMessage();
			e.printStackTrace();
		}
		return respGetPartnerJsonObj;
	}

	@Override
	public ResponseJsonObj getAvaliableDownloadFiles(String jsonString) {
		// Get the avaliable packages from TRUCore server
		PackageFilter fltr = new PackageFilter();
		// fltr.add(PackageFilterKeys.ALL_COMPANY_PACKAGES, "ALL");
		// fltr.add(PackageFilterKeys.STATUS, "Intransit");
		RespGetDownloadFilesJsonObj RespGetDownloadFilesJsonObj = new RespGetDownloadFilesJsonObj();
		try {
			TRUShareSimpleClient mTRUShareSimpleClient = new TRUShareSimpleClient(Constant.TRUSHARE_IDENTITY_URL, Constant.TRUSHARE_BASE_URL);
			ReqGetDownloadFilsJsonObj ReqGetDownloadFilsJsonObj = JsonHelper.parseObject(jsonString, ReqGetDownloadFilsJsonObj.class);
			SimpleIdentityToken token = tokenMap.get(ReqGetDownloadFilsJsonObj.token);
			IPackageList dt = mTRUShareSimpleClient.getPackages(token, fltr, PackageFilterType.RECEIVED, (long) 1);
			PackageList pl = (PackageList) dt;
			for (TPAPackage pgkhd : pl.list) {
				RespDownloadFileJsonObj downloadFileJsonObj = new RespDownloadFileJsonObj();
				PackageHandle handle = (PackageHandle) pgkhd.getHandle();
				String packageID = handle.toString();
				if (packageID.contains("/"))
					packageID = packageID.substring(packageID.lastIndexOf("/") + 1);
				TPAPackage mTPAPackage = (TPAPackage) mTRUShareSimpleClient.getPackage(token, pgkhd.getHandle());
				for (PackagePayload payload : mTPAPackage.payloads) {
					IMetaDataList metaData = payload.getMetaData();
					for (String label : metaData.getLabels()) {
						// [FileName, FileSize, FilePath]
						if (label.equals("FileName")) {
							downloadFileJsonObj.fileName = metaData.get("FileName");
						}
						if (label.equals("FileSize")) {
							downloadFileJsonObj.fileSize = metaData.get("FileSize");
						}
					}
				}
				downloadFileJsonObj.sender = mTPAPackage.getHeader().getCreator().asString();
				PackageDetails pkgDetail = PackageDetails.getPackageDetails(pgkhd);
				downloadFileJsonObj.status = pkgDetail.PackageStatus;
				System.out.println("   ["+pkgDetail.PackageStatus+"] "+downloadFileJsonObj.fileName+" "+downloadFileJsonObj.fileSize);
				if ("DELIVERED".equals(pkgDetail.PackageStatus)) {
					RespGetDownloadFilesJsonObj.downloadFiles.add(downloadFileJsonObj);
				}
			}
		} catch (Exception e) {
			RespGetDownloadFilesJsonObj.result = TrucoreMSService.FAILED;
			RespGetDownloadFilesJsonObj.log = e.getMessage();
			e.printStackTrace();
		}
		return RespGetDownloadFilesJsonObj;
	}

	@Override
	public ResponseJsonObj fileUpload(String tokenStr, List<File> uploadFiles, String encryFileFoder, String pfirstname, String plastname, String pemail) throws Exception {
		ResFileUploadJsonObj res = new ResFileUploadJsonObj();
		SimpleIdentityToken token = tokenMap.get(tokenStr);
		List<IUser> recipients = findPartners(token, pfirstname, plastname, pemail);
		MFXClient.encryptAndUploadAsync(token, recipients, uploadFiles, encryFileFoder);
		res.result = TrucoreMSService.SUCCESS;
		res.token = token.getAuthenticationToken();
		res.log = "You have successfully uploaded "+uploadFiles.size()+" file(s).";
//		UserProfile loginUser = (UserProfile) mProfileAdministrationStub.getMyProfile(token);
//		String msg = loginUser.firstName + " " + loginUser.lastName+" has uploaded a file "+uploadFiles.get(0).getName()+".";
//		pushNotificationsToiOSdevices(msg);
		return res;
	}

	/**
	 * Get partners
	 *
	 * @param communtiyName
	 * @param supplierCode
	 *            (If this supplier code is empty ,the result will query all of
	 *            partners)
	 * @return
	 * @throws ServiceException
	 */
	public List<IUser> findPartners(IIdentityToken token, String pfirstname, String plastname, String pemail) throws ServiceException {
		UserProfile myProfile = (UserProfile) mProfileAdministrationStub.getMyProfile(token);
		// Get community
		List<IMembershipGroupHandle> lsCommunities = mCommunityAdministrationStub.getCommunitiesOfUser(token, myProfile);
		Community community = (Community) lsCommunities.get(0);
		return mTRUShareSimpleClient.findPartners(token, community.getCommunityUniqueID(), "", "", "", pfirstname, plastname, pemail, "", "", "", 0, 1);
	}

	@Override
	public File fileDownload(String tokenStr, String filename,
			String downloadFolder) {
		SimpleIdentityToken token = tokenMap.get(tokenStr);
		// Get the avaliable packages from TRUCore server
		PackageFilter fltr = new PackageFilter();
		// fltr.add(PackageFilterKeys.ALL_COMPANY_PACKAGES, "ALL");
		// fltr.add(PackageFilterKeys.STATUS, "Intransit");
		IPackageList dt;
		try {
			dt = mTRUShareSimpleClient.getPackages(token, fltr, PackageFilterType.RECEIVED, (long) 1);

			PackageList pl = (PackageList) dt;
			if (pl.list.size() <= 0) {
				return null;
			}
//			List<String> files = new ArrayList<String>();
			outer:for (TPAPackage pkg : pl.list) {
				PackageHandle handle = (PackageHandle) pkg.getHandle();
				String packageID = handle.toString();
				if (packageID.contains("/"))
					packageID = packageID.substring(packageID.lastIndexOf("/") + 1);
				TPAPackage mTPAPackage = (TPAPackage) mTRUShareSimpleClient.getPackage(token, pkg.getHandle());
				for (PackagePayload payload : mTPAPackage.payloads) {
					IMetaDataList metaData = payload.getMetaData();
					for (String label : metaData.getLabels()) {
						if (label.equals("FileName")) {
							String fName = metaData.get("FileName");
							if (filename.equals(fName)) {
//								files.add(metaData.get(IMFXClient.FILE_PATH));
//								// get my private key for file decryption
//								// get package details and ASYNC call server I have done to download
//								// request
//								PackageDetails packageDetails = PackageDetails.getPackageDetails(mTPAPackage);
//								CommunityHandle communityHandle = new CommunityHandle(mCommunityAdministrationStub.handler.getBaseUrl() + "community/" + packageDetails.CommunityID, packageDetails.CommunityID);
//								// CommunityHandle communityHandle = new CommunityHandle("",
//								// packageDetails.CommunityID);
//								Community community = (Community) mIdentityResolverStub.getCommunity(token, communityHandle);// get
//								// communites
//								// details
//								UserProfile recipient = (UserProfile) mProfileAdministrationStub.getMyProfile(token);
//								KeyData recipientPrivateKeyInfo = new KeyData();
//								recipientPrivateKeyInfo.setKeyType(KeyType.UserPrivateKeyOnServer);
//								recipientPrivateKeyInfo.setUserHandle(recipient);
//								if (community.getEncryptionType() == CommunityEncryptionType.CommunityKeyEncryption) {
//									recipientPrivateKeyInfo.setCommunityHandle(communityHandle);
//									recipientPrivateKeyInfo.setKeyType(KeyType.Community);
//								}

//								MFXClient.downloadAndDecryptFiles(token, keyStore, recipientPrivateKeyInfo, packageID, files, downloadFolder + Constant.DOWNLOAD_FOLDER, true);
								List<TPAPackage> pkgList = new ArrayList<TPAPackage>();
								pkgList.add(pkg);
								MFXClient.downloadAdnDecryptFiles(token, pkgList, downloadFolder + Constant.DOWNLOAD_FOLDER);
								//.downloadFile(uToken, packageID, fileName, targetDir, startByte)

								File returnFile = new File(downloadFolder + Constant.TC_UPLOAD_FOLDER+"/"+filename);
								System.out.println("########"+downloadFolder +Constant.TC_UPLOAD_FOLDER+"/"+filename+"########");
								if (returnFile.exists()) {
									return returnFile;
								}

								break outer;
							}
						}
					}
				}
			}
		} catch (ServiceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	/**
	 *
	 * @param msg
	 */
	private void pushNotificationsToiOSdevices(String msg) {
		InputStream keystore  = TrucoreMSServiceImpl.class.getClassLoader().getResourceAsStream("com/rocket/tms/service/RLinkAPNS.p12");
        try {
			Push.alert(msg, keystore, "123456", false, IOStoken);
		} catch (CommunicationException e) {
			e.printStackTrace();
		} catch (KeystoreException e) {
			e.printStackTrace();
		} finally {
			try {
				keystore.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String argz[]) {
		RespGetPartnerJsonObj respGetPartnerJsonObj = new RespGetPartnerJsonObj();
		RespPartner partner1 = new RespPartner();
		partner1.username = "xxu";
		partner1.company = "rocket";
		RespPartner partner2 = new RespPartner();
		partner2.username = "xxu";
		partner2.company = "rocket";
		respGetPartnerJsonObj.partners.add(partner1);
		respGetPartnerJsonObj.partners.add(partner2);
		String result = JsonHelper.toJSON(respGetPartnerJsonObj);
		System.out.println(result);
	}

}


text:
require 'json'

module HyperMapper
  module Document
    class EmbeddedCollection
      include Enumerable

      def initialize(options={})
        @klass = options[:class]
        @parent = options[:parent]
        @klass_plural = @klass.name.to_s.underscore

        children = options[:values] ? options[:values].value : nil

        @elements = {}
        if children.is_a? Hash
          initialize_from_json_map children
        elsif children.is_a? Array
          initialize_from_array children
        end
      end

      def initialize_from_array(arr)
        arr.each do |attrs|
          child = @klass.load_from_attrs attrs
          @elements[child.key_value] = child
          child.parent = @parent
          child.persisted = false
        end
      end

      def initialize_from_json_map(map)
        map.each do |k, attrs|
          child = add_from_json k, attrs
          child.persisted = true
        end
      end

      def find(id)
        @elements[id.to_s]
      end

      def remove(item)
        @elements.delete(item.id) if @elements.has_key?(item.id)
        delete = {}
        delete[@klass.embedded_collection_name] = {}
        delete[@klass.embedded_collection_name][item.id] = "dummy"
        Config.client.map_remove @parent.class.space_name,
                                 @parent.key_value,
                                 delete
        item
      end

      def <<(item)

        @elements[item.key_value.to_s] = item
        item.parent = @parent
        item.save unless item.persisted?

        item
      end

      def length
        @elements.length
      end

      def each
        (@elements || {}).each { |k,v| yield(v) }
      end

      def to_json
        @elements.inject({}) do |acc, (_, child)|
          child_json = child.serializable_hash
          child_json.delete @klass.key_name
          acc[child.key_value.to_s] = child_json.to_json
          acc
        end
      end

      def all
        @elements.map { |k, child| child }
      end

      def add_from_json(k, json)
        child = from_json! json
        child.send("#{@klass.key_name}=", k)
        child.persisted = true
        self.<< child
        child
      end

      def from_json!(json_map)
        instance = @klass.new
        JSON.load(json_map).each do |attr, val|
          instance.send("#{attr}=", val)
        end
        instance
      end

      def create(attrs)
        child = @klass.new(attrs)
        child.parent = @parent
        child.save
        self.<< child if child.valid?
        child
      end

      def create!(attrs)
        child = @klass.new(attrs)
        child.parent = @parent
        child.save!
        self.<< child
        child
      end

      def build(attrs={})
        child = @klass.new(attrs)
        @elements[child.key_value] = child
        child.parent = @parent
        child
      end

      def where(params={})
        msg = "where queries are not supported on embedded collections"
        raise Exceptions::NotSupportedException.new msg
      end
    end
  end
end


text:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="170dp"
    android:background="@android:color/white"
    android:paddingBottom="@dimen/padding_size_medium"
    android:paddingLeft="@dimen/padding_size_default"
    android:paddingRight="@dimen/padding_size_default"
    android:paddingTop="@dimen/padding_size_default"
    >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:id="@+id/related_movies_header"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="推荐"
            android:paddingLeft="5dp"
            />

        <android.support.v7.widget.RecyclerView
            android:id="@+id/related_recyclerview"
            android:layout_width="match_parent"
            android:layout_height="180dp"/>

    </LinearLayout>

</RelativeLayout>


text:
#ifndef _ED25519_RANDOMBYTES_H_
#define _ED25519_RANDOMBYTES_H_

static inline void ed25519_randombytes(unsigned char *, unsigned long long);

#endif /* _ED25519_RANDOMBYTES_H_ */


text:
package net.tridentsdk.event.player;

import lombok.Getter;
import lombok.Setter;
import net.tridentsdk.entity.living.Player;
import net.tridentsdk.ui.chat.ChatComponent;

/**
 * Represents a player that has successfully logged off the
 * server, and will commence with sending the necessary
 * packets in order to spawn the player entity later on.
 *
 * @author TridentSDK
 * @since 0.5-alpha
 */
@Getter
public class PlayerQuitEvent extends PlayerEvent {

    @Setter private ChatComponent message;

    public PlayerQuitEvent(Player player, ChatComponent message) {
        super(player);
        this.message = message;
    }

}


text:
@implementation FileProcessor

- (BOOL)processFile:(NSString*) filename {
    NSError *error = nil;
    NSString *fileContent = [NSString stringWithContentsOfFile:filename encoding:NSUTF8StringEncoding error:&error];
    if (error != nil) {
        NSLog(@"FileProcessor: cannot read file '%@': %@", filename, [error localizedDescription]);
        return NO;
    }
    NSLog(@"length: %ld",[fileContent length]);
    NSUInteger options = NSLinguisticTaggerJoinNames | NSLinguisticTaggerOmitWhitespace | NSLinguisticTaggerOmitPunctuation;
    NSLinguisticTagger *tagger = [[NSLinguisticTagger alloc] initWithTagSchemes:@[NSLinguisticTagSchemeLanguage, NSLinguisticTagSchemeLemma, NSLinguisticTagSchemeNameTypeOrLexicalClass] options:options];
    [tagger setString:fileContent];

    [tagger setOrthography:[NSOrthography orthographyWithDominantScript:@"Latn" languageMap:@{@"Latn": @[@"en"]}] range:NSMakeRange(0, [fileContent length])];

    NSUInteger sentenceCounter = 0;
    NSRange currentSentence = [tagger sentenceRangeForRange:NSMakeRange(0, 1)];
    NSLog(@"First sentence is %@", NSStringFromRange(currentSentence));
    while (currentSentence.location != NSNotFound) {
        __block NSUInteger tokenPosition = 0;
        [tagger enumerateTagsInRange:currentSentence
                              scheme:NSLinguisticTagSchemeNameTypeOrLexicalClass
                             options:options
                          usingBlock:^(NSString *tag, NSRange tokenRange, NSRange sentenceRange, BOOL *stop) {
                              NSString *token = [fileContent substringWithRange:tokenRange];
                              NSString *lemma = [tagger tagAtIndex:tokenRange.location scheme:NSLinguisticTagSchemeLemma tokenRange: NULL sentenceRange:NULL];
                              if (lemma == nil) {
                                  lemma = token;
                              }
                              [self.delegate receiveWord:@{@"token": token,@"postag": tag, @"lemma": lemma, @"position":  @(tokenPosition), @"sentence": @(sentenceCounter), @"filename": filename}];
                              tokenPosition++;
                          }];
        sentenceCounter++;
        if (currentSentence.location + currentSentence.length == [fileContent length]) {
            currentSentence.location = NSNotFound;
        } else {
            NSRange nextSentence = NSMakeRange(currentSentence.location + currentSentence.length + 1, 1);
            currentSentence = [tagger sentenceRangeForRange:nextSentence];
            NSLog(@"current sentence is %@", NSStringFromRange(currentSentence));
        }
    }
    return YES;
}

@end


text:
package com.example.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

import java.io.Serializable;
import java.util.Set;

@Entity
//@JsonIgnoreProperties("books")
public class Author implements Serializable
{

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    private Integer id;

    private String name;

    @ManyToMany(mappedBy = "authors")
    private Set<Book> books;

    public Author()
    {
        super();
    }

    public Author(String name)
    {
        super();
        this.name = name;
    }

    public Integer getId()
    {
        return id;
    }

    public void setId(Integer id)
    {
        this.id = id;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public Set<Book> getBooks()
    {
        return books;
    }

    public void setBooks(Set<Book> books)
    {
        this.books = books;
    }

    @Override
    public String toString()
    {
        return String.format("Author [id=%s, name=%s, books=%s]", id, name, books);
    }

}


text:
package com.cisco.ukidcv.spark.tasks.inventory;

import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;

import com.cisco.ukidcv.spark.constants.SparkConstants;
import com.cloupia.model.cIM.FormFieldDefinition;
import com.cloupia.service.cIM.inframgr.TaskConfigIf;
import com.cloupia.service.cIM.inframgr.customactions.UserInputField;
import com.cloupia.service.cIM.inframgr.forms.wizard.FormField;

/**
 * Configuration task to collect inventory.
 * <p>
 * This provides the GUI and configuration elements to execute this task. It can
 * be used via an action button or as a workflow task.
 *
 * @author Matt Day
 *
 */
@PersistenceCapable(detachable = "true", table = "Spark_inventory_collection")
public class CollectInventoryConfig implements TaskConfigIf {

	@Persistent
	private long configEntryId;

	@Persistent
	private long actionId;

	@FormField(label = SparkConstants.ACCOUNT_LIST_FORM_LABEL, help = SparkConstants.ACCOUNT_LIST_FORM_LABEL, mandatory = true, type = FormFieldDefinition.FIELD_TYPE_TABULAR_POPUP, table = SparkConstants.ACCOUNT_LIST_FORM_PROVIDER)
	@UserInputField(type = SparkConstants.ACCOUNT_LIST_FORM_TABLE_NAME)
	@Persistent
	private String account;

	/**
	 * Empty default constructor - you could initialise default values here if
	 * you wanted
	 */
	public CollectInventoryConfig() {

	}

	@Override
	public long getActionId() {
		return this.actionId;
	}

	@Override
	public long getConfigEntryId() {
		return this.configEntryId;
	}

	@Override
	public String getDisplayLabel() {
		return SparkConstants.INVENTORY_TASK_LABEL;
	}

	/**
	 * Get the account name
	 *
	 * @return Account name to do this on
	 */
	public String getAccount() {
		return this.account;
	}

	/**
	 * Set the account name
	 *
	 * @param account
	 *            The host to be created
	 */
	public void setAccount(String account) {
		this.account = account;
	}

	@Override
	public void setActionId(long actionId) {
		this.actionId = actionId;
	}

	@Override
	public void setConfigEntryId(long configEntryId) {
		this.configEntryId = configEntryId;
	}
}


text:
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```ts

// @public
export type AsyncFactoryFn<T> = () => Promise<T>;

// @public
export type AsyncOptionPredicate<T, O> = (item: T, option: O) => Promise<boolean>;

// @public
export type AsyncPredicate<T> = (item: T) => Promise<boolean>;

// @public
export interface AutoChangeDetectionStatus {
    isDisabled: boolean;
    onDetectChangesNow?: () => void;
}

// @public
export interface BaseHarnessFilters {
    ancestor?: string;
    selector?: string;
}

// @public
export abstract class ComponentHarness {
    constructor(locatorFactory: LocatorFactory);
    protected documentRootLocatorFactory(): LocatorFactory;
    protected forceStabilize(): Promise<void>;
    host(): Promise<TestElement>;
    // (undocumented)
    protected readonly locatorFactory: LocatorFactory;
    protected locatorFor<T extends (HarnessQuery<any> | string)[]>(...queries: T): AsyncFactoryFn<LocatorFnResult<T>>;
    protected locatorForAll<T extends (HarnessQuery<any> | string)[]>(...queries: T): AsyncFactoryFn<LocatorFnResult<T>[]>;
    protected locatorForOptional<T extends (HarnessQuery<any> | string)[]>(...queries: T): AsyncFactoryFn<LocatorFnResult<T> | null>;
    protected waitForTasksOutsideAngular(): Promise<void>;
}

// @public
export interface ComponentHarnessConstructor<T extends ComponentHarness> {
    // (undocumented)
    new (locatorFactory: LocatorFactory): T;
    hostSelector: string;
}

// @public
export abstract class ContentContainerComponentHarness<S extends string = string> extends ComponentHarness implements HarnessLoader {
    // (undocumented)
    getAllChildLoaders(selector: S): Promise<HarnessLoader[]>;
    // (undocumented)
    getAllHarnesses<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T[]>;
    // (undocumented)
    getChildLoader(selector: S): Promise<HarnessLoader>;
    // (undocumented)
    getHarness<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T>;
    // (undocumented)
    getHarnessOrNull<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T | null>;
    protected getRootHarnessLoader(): Promise<HarnessLoader>;
    // (undocumented)
    hasHarness<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<boolean>;
}

// @public
export interface ElementDimensions {
    // (undocumented)
    height: number;
    // (undocumented)
    left: number;
    // (undocumented)
    top: number;
    // (undocumented)
    width: number;
}

// @public
export type EventData = string | number | boolean | Function | undefined | null | EventData[] | {
    [key: string]: EventData;
};

// @public
export function getNoKeysSpecifiedError(): Error;

// @public
export function _getTextWithExcludedElements(element: Element, excludeSelector: string): string;

// @public
export function handleAutoChangeDetectionStatus(handler: (status: AutoChangeDetectionStatus) => void): void;

// @public
export abstract class HarnessEnvironment<E> implements HarnessLoader, LocatorFactory {
    protected constructor(rawRootElement: E);
    protected createComponentHarness<T extends ComponentHarness>(harnessType: ComponentHarnessConstructor<T>, element: E): T;
    protected abstract createEnvironment(element: E): HarnessEnvironment<E>;
    protected abstract createTestElement(element: E): TestElement;
    // (undocumented)
    documentRootLocatorFactory(): LocatorFactory;
    // (undocumented)
    abstract forceStabilize(): Promise<void>;
    // (undocumented)
    getAllChildLoaders(selector: string): Promise<HarnessLoader[]>;
    // (undocumented)
    getAllHarnesses<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T[]>;
    protected abstract getAllRawElements(selector: string): Promise<E[]>;
    // (undocumented)
    getChildLoader(selector: string): Promise<HarnessLoader>;
    protected abstract getDocumentRoot(): E;
    // (undocumented)
    getHarness<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T>;
    // (undocumented)
    getHarnessOrNull<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T | null>;
    // (undocumented)
    harnessLoaderFor(selector: string): Promise<HarnessLoader>;
    // (undocumented)
    harnessLoaderForAll(selector: string): Promise<HarnessLoader[]>;
    // (undocumented)
    harnessLoaderForOptional(selector: string): Promise<HarnessLoader | null>;
    // (undocumented)
    hasHarness<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<boolean>;
    // (undocumented)
    locatorFor<T extends (HarnessQuery<any> | string)[]>(...queries: T): AsyncFactoryFn<LocatorFnResult<T>>;
    // (undocumented)
    locatorForAll<T extends (HarnessQuery<any> | string)[]>(...queries: T): AsyncFactoryFn<LocatorFnResult<T>[]>;
    // (undocumented)
    locatorForOptional<T extends (HarnessQuery<any> | string)[]>(...queries: T): AsyncFactoryFn<LocatorFnResult<T> | null>;
    // (undocumented)
    protected rawRootElement: E;
    // (undocumented)
    get rootElement(): TestElement;
    set rootElement(element: TestElement);
    // (undocumented)
    rootHarnessLoader(): Promise<HarnessLoader>;
    // (undocumented)
    abstract waitForTasksOutsideAngular(): Promise<void>;
}

// @public
export interface HarnessLoader {
    getAllChildLoaders(selector: string): Promise<HarnessLoader[]>;
    getAllHarnesses<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T[]>;
    getChildLoader(selector: string): Promise<HarnessLoader>;
    getHarness<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T>;
    getHarnessOrNull<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T | null>;
    hasHarness<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<boolean>;
}

// @public
export class HarnessPredicate<T extends ComponentHarness> {
    constructor(harnessType: ComponentHarnessConstructor<T>, options: BaseHarnessFilters);
    add(description: string, predicate: AsyncPredicate<T>): this;
    addOption<O>(name: string, option: O | undefined, predicate: AsyncOptionPredicate<T, O>): this;
    evaluate(harness: T): Promise<boolean>;
    filter(harnesses: T[]): Promise<T[]>;
    getDescription(): string;
    getSelector(): string;
    // (undocumented)
    harnessType: ComponentHarnessConstructor<T>;
    static stringMatches(value: string | null | Promise<string | null>, pattern: string | RegExp | null): Promise<boolean>;
}

// @public
export type HarnessQuery<T extends ComponentHarness> = ComponentHarnessConstructor<T> | HarnessPredicate<T>;

// @public
export interface LocatorFactory {
    documentRootLocatorFactory(): LocatorFactory;
    forceStabilize(): Promise<void>;
    harnessLoaderFor(selector: string): Promise<HarnessLoader>;
    harnessLoaderForAll(selector: string): Promise<HarnessLoader[]>;
    harnessLoaderForOptional(selector: string): Promise<HarnessLoader | null>;
    locatorFor<T extends (HarnessQuery<any> | string)[]>(...queries: T): AsyncFactoryFn<LocatorFnResult<T>>;
    locatorForAll<T extends (HarnessQuery<any> | string)[]>(...queries: T): AsyncFactoryFn<LocatorFnResult<T>[]>;
    locatorForOptional<T extends (HarnessQuery<any> | string)[]>(...queries: T): AsyncFactoryFn<LocatorFnResult<T> | null>;
    rootElement: TestElement;
    rootHarnessLoader(): Promise<HarnessLoader>;
    waitForTasksOutsideAngular(): Promise<void>;
}

// @public
export type LocatorFnResult<T extends (HarnessQuery<any> | string)[]> = {
    [I in keyof T]: T[I] extends new (...args: any[]) => infer C ? C : T[I] extends {
        harnessType: new (...args: any[]) => infer C;
    } ? C : T[I] extends string ? TestElement : never;
}[number];

// @public
export function manualChangeDetection<T>(fn: () => Promise<T>): Promise<T>;

// @public
export interface ModifierKeys {
    // (undocumented)
    alt?: boolean;
    // (undocumented)
    control?: boolean;
    // (undocumented)
    meta?: boolean;
    // (undocumented)
    shift?: boolean;
}

// @public
export function parallel<T1, T2, T3, T4, T5>(values: () => [
T1 | PromiseLike<T1>,
T2 | PromiseLike<T2>,
T3 | PromiseLike<T3>,
T4 | PromiseLike<T4>,
T5 | PromiseLike<T5>
]): Promise<[T1, T2, T3, T4, T5]>;

// @public
export function parallel<T1, T2, T3, T4>(values: () => [
T1 | PromiseLike<T1>,
T2 | PromiseLike<T2>,
T3 | PromiseLike<T3>,
T4 | PromiseLike<T4>
]): Promise<[T1, T2, T3, T4]>;

// @public
export function parallel<T1, T2, T3>(values: () => [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]): Promise<[T1, T2, T3]>;

// @public
export function parallel<T1, T2>(values: () => [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<[T1, T2]>;

// @public
export function parallel<T>(values: () => (T | PromiseLike<T>)[]): Promise<T[]>;

// @public
export function stopHandlingAutoChangeDetectionStatus(): void;

// @public
export interface TestElement {
    blur(): Promise<void>;
    clear(): Promise<void>;
    click(modifiers?: ModifierKeys): Promise<void>;
    click(location: 'center', modifiers?: ModifierKeys): Promise<void>;
    click(relativeX: number, relativeY: number, modifiers?: ModifierKeys): Promise<void>;
    dispatchEvent(name: string, data?: Record<string, EventData>): Promise<void>;
    focus(): Promise<void>;
    getAttribute(name: string): Promise<string | null>;
    getCssValue(property: string): Promise<string>;
    getDimensions(): Promise<ElementDimensions>;
    getProperty<T = any>(name: string): Promise<T>;
    hasClass(name: string): Promise<boolean>;
    hover(): Promise<void>;
    isFocused(): Promise<boolean>;
    matchesSelector(selector: string): Promise<boolean>;
    mouseAway(): Promise<void>;
    rightClick(relativeX: number, relativeY: number, modifiers?: ModifierKeys): Promise<void>;
    selectOptions(...optionIndexes: number[]): Promise<void>;
    sendKeys(...keys: (string | TestKey)[]): Promise<void>;
    sendKeys(modifiers: ModifierKeys, ...keys: (string | TestKey)[]): Promise<void>;
    setInputValue(value: string): Promise<void>;
    text(options?: TextOptions): Promise<string>;
}

// @public
export enum TestKey {
    // (undocumented)
    ALT = 5,
    // (undocumented)
    BACKSPACE = 0,
    // (undocumented)
    CONTROL = 4,
    // (undocumented)
    DELETE = 16,
    // (undocumented)
    DOWN_ARROW = 14,
    // (undocumented)
    END = 9,
    // (undocumented)
    ENTER = 2,
    // (undocumented)
    ESCAPE = 6,
    // (undocumented)
    F1 = 17,
    // (undocumented)
    F10 = 26,
    // (undocumented)
    F11 = 27,
    // (undocumented)
    F12 = 28,
    // (undocumented)
    F2 = 18,
    // (undocumented)
    F3 = 19,
    // (undocumented)
    F4 = 20,
    // (undocumented)
    F5 = 21,
    // (undocumented)
    F6 = 22,
    // (undocumented)
    F7 = 23,
    // (undocumented)
    F8 = 24,
    // (undocumented)
    F9 = 25,
    // (undocumented)
    HOME = 10,
    // (undocumented)
    INSERT = 15,
    // (undocumented)
    LEFT_ARROW = 11,
    // (undocumented)
    META = 29,
    // (undocumented)
    PAGE_DOWN = 8,
    // (undocumented)
    PAGE_UP = 7,
    // (undocumented)
    RIGHT_ARROW = 13,
    // (undocumented)
    SHIFT = 3,
    // (undocumented)
    TAB = 1,
    // (undocumented)
    UP_ARROW = 12
}

// @public (undocumented)
export interface TextOptions {
    exclude?: string;
}

// (No @packageDocumentation comment for this package)

```


text:
class Adaptor < Sinatra::Base
  post '/new_download_received' do
    begin
      require 'pp'

      pp request.env
      pp request.env["rack.request.form_hash"]
      pp request.env["rack.input"].inspect

      uploaded_file = params['uploadedfile']
      raise 'No upload file specified' if !uploaded_file
      tempfile = uploaded_file[:tempfile]

      @handler.handle_new_download_received(uploaded_file[:filename], tempfile, params[:async] || 'true')
    rescue StandardError => e
      [:status=>'failed', 'message'=>e.message]
    ensure
      if tempfile
        tempfile.close
        tempfile.delete
      end
    end
  end

end


text:
class AddSelection < ActiveRecord::Migration
  def change
    add_column :library_memberships, :selection, :text
  end
end