text:
package org.camunda.bpm.engine.test.assertions.bpmn;

import static java.lang.String.format;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.assertj.core.api.Assertions;
import org.camunda.bpm.engine.AuthorizationService;
import org.camunda.bpm.engine.DecisionService;
import org.camunda.bpm.engine.ExternalTaskService;
import org.camunda.bpm.engine.FormService;
import org.camunda.bpm.engine.HistoryService;
import org.camunda.bpm.engine.IdentityService;
import org.camunda.bpm.engine.ManagementService;
import org.camunda.bpm.engine.RepositoryService;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.TaskService;
import org.camunda.bpm.engine.exception.NotFoundException;
import org.camunda.bpm.engine.externaltask.ExternalTask;
import org.camunda.bpm.engine.externaltask.ExternalTaskQuery;
import org.camunda.bpm.engine.externaltask.LockedExternalTask;
import org.camunda.bpm.engine.repository.ProcessDefinition;
import org.camunda.bpm.engine.repository.ProcessDefinitionQuery;
import org.camunda.bpm.engine.runtime.ExecutionQuery;
import org.camunda.bpm.engine.runtime.Job;
import org.camunda.bpm.engine.runtime.JobQuery;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.bpm.engine.runtime.ProcessInstanceQuery;
import org.camunda.bpm.engine.task.Task;
import org.camunda.bpm.engine.task.TaskQuery;
import org.camunda.bpm.model.bpmn.BpmnModelInstance;
import org.camunda.bpm.model.bpmn.instance.Activity;
import org.camunda.bpm.model.bpmn.instance.Event;
import org.camunda.bpm.model.bpmn.instance.Gateway;

/**
 * Convenience class to access only camunda *BPMN* related Assertions
 * PLUS helper methods. Usage is possible, if you only need BPMN Tests and
 * mandatory if you still use Camunda Platform lower than 7.2 version.
 *
 * Use it with a static import:
 *
 * import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.*;
 *
 * @see org.camunda.bpm.engine.test.assertions.ProcessEngineTests
 *      for full Camunda Platform Assertions functionality
 *
 */
public class BpmnAwareTests extends AbstractAssertions {

  private static final String DUPLICATED_NAME = "$DUPLICATED_NAME$";
  public static final long DEFAULT_LOCK_DURATION_EXTERNAL_TASK = 30L * 1000L;// 30 seconds
  public static final String DEFAULT_WORKER_EXTERNAL_TASK      = "anonymousWorker";

  protected BpmnAwareTests() {}

  /**
   * Assert that... the given ProcessDefinition meets your expectations.
   *
   * @param   actual ProcessDefinition under test
   * @return  Assert object offering ProcessDefinition specific assertions.
   */
  public static ProcessDefinitionAssert assertThat(final ProcessDefinition actual) {
    return ProcessDefinitionAssert.assertThat(processEngine(), actual);
  }

  /**
   * Assert that... the given ProcessInstance meets your expectations.
   *
   * @param   actual ProcessInstance under test
   * @return  Assert object offering ProcessInstance specific assertions.
   */
  public static ProcessInstanceAssert assertThat(final ProcessInstance actual) {
    return ProcessInstanceAssert.assertThat(processEngine(), actual);
  }

  /**
   * Assert that... the given Task meets your expectations.
   *
   * @param   actual Task under test
   * @return  Assert object offering Task specific assertions.
   */
  public static TaskAssert assertThat(final Task actual) {
    return TaskAssert.assertThat(processEngine(), actual);
  }

  /**
   * Assert that... the given ExternalTask meets your expectations.
   *
   * @param   actual ExternalTask under test
   * @return  Assert object offering Task specific assertions.
   */
  public static ExternalTaskAssert assertThat(final ExternalTask actual) {
    return ExternalTaskAssert.assertThat(processEngine(), actual);
  }

  /**
   * Assert that... the given Job meets your expectations.
   *
   * @param   actual Job under test
   * @return  Assert object offering Job specific assertions.
   */
  public static JobAssert assertThat(final Job actual) {
    return JobAssert.assertThat(processEngine(), actual);
  }

  /**
   * Helper method to easily access RuntimeService
   *
   * @return  RuntimeService of process engine bound to this testing thread
   * @see     org.camunda.bpm.engine.RuntimeService
   */
  public static RuntimeService runtimeService() {
    return processEngine().getRuntimeService();
  }

  /**
   * Helper method to easily access AuthorizationService
   *
   * @return  AuthorizationService of process engine bound to this
   *          testing thread
   * @see     org.camunda.bpm.engine.AuthorizationService
   */
  public static AuthorizationService authorizationService() {
    return processEngine().getAuthorizationService();
  }

  /**
   * Helper method to easily access FormService
   *
   * @return  FormService of process engine bound to this testing thread
   * @see     org.camunda.bpm.engine.FormService
   */
  public static FormService formService() {
    return processEngine().getFormService();
  }

  /**
   * Helper method to easily access HistoryService
   *
   * @return  HistoryService of process engine bound to this testing thread
   * @see     org.camunda.bpm.engine.HistoryService
   */
  public static HistoryService historyService() {
    return processEngine().getHistoryService();
  }

  /**
   * Helper method to easily access IdentityService
   *
   * @return  IdentityService of process engine bound to this testing thread
   * @see     org.camunda.bpm.engine.IdentityService
   */
  public static IdentityService identityService() {
    return processEngine().getIdentityService();
  }

  /**
   * Helper method to easily access ManagementService
   *
   * @return  ManagementService of process engine bound to this testing thread
   * @see     org.camunda.bpm.engine.ManagementService
   */
  public static ManagementService managementService() {
    return processEngine().getManagementService();
  }

  /**
   * Helper method to easily access RepositoryService
   *
   * @return  RepositoryService of process engine bound to this testing thread
   * @see     org.camunda.bpm.engine.RepositoryService
   */
  public static RepositoryService repositoryService() {
    return processEngine().getRepositoryService();
  }

  /**
   * Helper method to easily access TaskService
   *
   * @return  TaskService of process engine bound to this testing thread
   * @see     org.camunda.bpm.engine.TaskService
   */
  public static TaskService taskService() {
    return processEngine().getTaskService();
  }

  /**
   * Helper method to easily access ExternalTaskService
   *
   * @return ExternalTaskService of process engine bound to this testing thread
   * @see org.camunda.bpm.engine.ExternalTaskService
   */
  public static ExternalTaskService externalTaskService() {
    return processEngine().getExternalTaskService();
  }

  /**
   * Helper method to easily access DecisionService
   *
   * @return DecisionService of process engine bound to this testing thread
   * @see org.camunda.bpm.engine.DecisionService
   */
  public static DecisionService decisionService() {
    return processEngine().getDecisionService();
  }

  /**
   * Helper method to easily create a new TaskQuery
   *
   * @return  new TaskQuery for process engine bound to this testing thread
   * @see     org.camunda.bpm.engine.task.TaskQuery
   */
  public static TaskQuery taskQuery() {
    return taskService().createTaskQuery();
  }

  /**
   * Helper method to easily create a new ExternalTaskQuery
   *
   * @return  new ExternalTaskQuery for process engine bound to this testing thread
   * @see     org.camunda.bpm.engine.externaltask.ExternalTaskQuery
   */
  public static ExternalTaskQuery externalTaskQuery() {
    return externalTaskService().createExternalTaskQuery();
  }

  /**
   * Helper method to easily create a new JobQuery
   *
   * @return  new JobQuery for process engine bound to this testing thread
   * @see     org.camunda.bpm.engine.runtime.JobQuery
   */
  public static JobQuery jobQuery() {
    return managementService().createJobQuery();
  }

  /**
   * Helper method to easily create a new ProcessInstanceQuery
   *
   * @return  new ProcessInstanceQuery for process engine bound to this
   *          testing thread
   * @see     org.camunda.bpm.engine.runtime.ProcessInstanceQuery
   */
  public static ProcessInstanceQuery processInstanceQuery() {
    return runtimeService().createProcessInstanceQuery();
  }

  /**
   * Helper method to easily create a new ProcessDefinitionQuery
   *
   * @return  new ProcessDefinitionQuery for process engine bound to this
   *          testing thread
   * @see     org.camunda.bpm.engine.repository.ProcessDefinitionQuery
   */
  public static ProcessDefinitionQuery processDefinitionQuery() {
    return repositoryService().createProcessDefinitionQuery();
  }

  /**
   * Helper method to easily create a new ExecutionQuery
   *
   * @return  new ExecutionQuery for process engine bound to this testing thread
   * @see     org.camunda.bpm.engine.runtime.ExecutionQuery
   */
  public static ExecutionQuery executionQuery() {
    return runtimeService().createExecutionQuery();
  }

  /**
   * Helper method to easily construct a map of process variables
   *
   * @param   key (obligatory) key of first process variable
   * @param   value (obligatory) value of first process variable
   * @param   furtherKeyValuePairs (optional) key/value pairs for further
   *          process variables
   * @return  a map of process variables by passing a list of String,
   *          Object key value pairs.
   */
  public static Map<String, Object> withVariables(final String key, final Object value, final Object... furtherKeyValuePairs) {
    if (key == null)
      throw new IllegalArgumentException(format("Illegal call of withVariables(key = '%s', value = '%s', ...) - key must not be null!", key, value));
    final Map<String, Object> map = new HashMap<>();
    map.put(key, value);
    if (furtherKeyValuePairs != null) {
      if (furtherKeyValuePairs.length % 2 != 0) {
        throw new IllegalArgumentException(format("Illegal call of withVariables() - must have an even number of arguments, but found length = %s!", furtherKeyValuePairs.length + 2));
      }
      for (int i = 0; i < furtherKeyValuePairs.length; i += 2) {
        if (!(furtherKeyValuePairs[i] instanceof String))
          throw new IllegalArgumentException(format("Illegal call of withVariables() - keys must be strings, found object of type '%s'!", furtherKeyValuePairs[i] != null ? furtherKeyValuePairs[i].getClass().getName() : null));
        map.put((String) furtherKeyValuePairs[i], furtherKeyValuePairs[i + 1]);
      }
    }
    return map;
  }

  /**
   * Helper method to easily access the only task currently
   * available in the context of the last asserted process
   * instance.
   *
   * @return  the only task of the last asserted process
   *          instance. May return null if no such task exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one task is delivered by the underlying
   *          query or in case no process instance was asserted
   *          yet.
   */
  public static Task task() {
    return task(taskQuery());
  }

  /**
   * Helper method to easily access the only task currently
   * available in the context of the given process instance.
   *
   * @param   processInstance the process instance for which
   *          a task should be retrieved.
   * @return  the only task of the process instance. May
   *          return null if no such task exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one task is delivered by the underlying
   *          query.
   */
  public static Task task(ProcessInstance processInstance) {
    return task(taskQuery(), processInstance);
  }

  /**
   * Helper method to easily access the only task with the
   * given taskDefinitionKey currently available in the context
   * of the last asserted process instance.
   *
   * @param   taskDefinitionKey the key of the task that should
   *          be retrieved.
   * @return  the only task of the last asserted process
   *          instance. May return null if no such task exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one task is delivered by the underlying
   *          query or in case no process instance was asserted
   *          yet.
   */
  public static Task task(String taskDefinitionKey) {
    Assertions.assertThat(taskDefinitionKey).isNotNull();
    return task(taskQuery().taskDefinitionKey(taskDefinitionKey));
  }

  /**
   * Helper method to easily access the only task with the
   * given taskDefinitionKey currently available in the context
   * of the given process instance.
   *
   * @param   taskDefinitionKey the key of the task that should
   *          be retrieved.
   * @param   processInstance the process instance for which
   *          a task should be retrieved.
   * @return  the only task of the given process instance. May
   *          return null if no such task exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one task is delivered by the underlying
   *          query.
   */
  public static Task task(String taskDefinitionKey, ProcessInstance processInstance) {
    Assertions.assertThat(taskDefinitionKey).isNotNull();
    return task(taskQuery().taskDefinitionKey(taskDefinitionKey), processInstance);
  }

  /**
   * Helper method to easily access the only task compliant to
   * a given taskQuery and currently available in the context
   * of the last asserted process instance.
   *
   * @param   taskQuery the query with which the task should
   *          be retrieved. This query will be further narrowed
   *          to the last asserted process instance.
   * @return  the only task of the last asserted process instance
   *          and compliant to the given query. May return null
   *          in case no such task exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one task is delivered by the underlying
   *          query or in case no process instance was asserted
   *          yet.
   */
  public static Task task(TaskQuery taskQuery) {
    ProcessInstanceAssert lastAssert = AbstractProcessAssert.getLastAssert(ProcessInstanceAssert.class);
    if (lastAssert == null)
      throw new IllegalStateException(
        "Call a process instance assertion first - " +
          "e.g. assertThat(processInstance)... !"
      );
    return task(taskQuery, lastAssert.getActual());
  }

  /**
   * Helper method to easily access the only task compliant to
   * a given taskQuery and currently available in the context
   * of the given process instance.
   *
   * @param   taskQuery the query with which the task should
   *          be retrieved. This query will be further narrowed
   *          to the given process instance.
   * @param   processInstance the process instance for which
   *          a task should be retrieved.
   * @return  the only task of the given process instance and
   *          compliant to the given query. May return null in
   *          case no such task exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one task is delivered by the underlying
   *          query.
   */
  public static Task task(TaskQuery taskQuery, ProcessInstance processInstance) {
    return assertThat(processInstance).isNotNull().task(taskQuery).getActual();
  }

  /**
   * Helper method to easily access the only external task currently
   * available in the context of the last asserted process instance.
   *
   * @return the only external task of the last asserted process instance.
   *         May return null if no such external task exists.
   * @throws java.lang.IllegalStateException
   *           in case more than one external task is delivered by the underlying
   *           query or in case no process instance was asserted yet.
   */
  public static ExternalTask externalTask() {
    return externalTask(externalTaskQuery());
  }

  /**
   * Helper method to easily access the only external task currently
   * available in the context of the given process instance.
   *
   * @param   processInstance the process instance for which
   *          an external task should be retrieved.
   * @return  the only external task of the process instance.
   *          May return null if no such external task exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one external task is delivered by the underlying
   *          query.
   */
  public static ExternalTask externalTask(ProcessInstance processInstance) {
    return externalTask(externalTaskQuery(), processInstance);
  }

  /**
   * Helper method to easily access the only external task with the
   * given activityId currently available in the context
   * of the last asserted process instance.
   *
   * @param   activityId the key of the external task that should
   *          be retrieved.
   * @return  the only external task of the last asserted process
   *          instance. May return null if no such external task exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one external task is delivered by the underlying
   *          query or in case no process instance was asserted
   *          yet.
   */
  public static ExternalTask externalTask(String activityId) {
    Assertions.assertThat(activityId).isNotNull();
    return externalTask(externalTaskQuery().activityId(activityId));
  }

  /**
   * Helper method to easily access the only external task with the
   * given activityId currently available in the context
   * of the given process instance.
   *
   * @param   activityId the key of the external task that should
   *          be retrieved.
   * @param   processInstance the process instance for which
   *          a external task should be retrieved.
   * @return  the only external task of the given process instance. May
   *          return null if no such external task exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one external task is delivered by the underlying
   *          query.
   */
  public static ExternalTask externalTask(String activityId, ProcessInstance processInstance) {
    Assertions.assertThat(activityId).isNotNull();
    return externalTask(externalTaskQuery().activityId(activityId), processInstance);
  }

  /**
   * Helper method to easily access the only external task compliant to
   * a given externalTaskQuery and currently available in the context
   * of the last asserted process instance.
   *
   * @param   externalTaskQuery the query with which the external task should
   *          be retrieved. This query will be further narrowed
   *          to the last asserted process instance.
   * @return  the only external task of the last asserted process instance
   *          and compliant to the given query. May return null
   *          in case no such external task exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one external task is delivered by the underlying
   *          query or in case no process instance was asserted
   *          yet.
   */
  public static ExternalTask externalTask(ExternalTaskQuery externalTaskQuery) {
    ProcessInstanceAssert lastAssert = AbstractProcessAssert.getLastAssert(ProcessInstanceAssert.class);
    if (lastAssert == null)
      throw new IllegalStateException(
        "Call a process instance assertion first - " +
          "e.g. assertThat(processInstance)... !"
      );
    return externalTask(externalTaskQuery, lastAssert.getActual());
  }

  /**
   * Helper method to easily access the only external task compliant to
   * a given externalTaskQuery and currently available in the context
   * of the given process instance.
   *
   * @param   externalTaskQuery the query with which the external task should
   *          be retrieved. This query will be further narrowed
   *          to the given process instance.
   * @param   processInstance the process instance for which
   *          a external task should be retrieved.
   * @return  the only external task of the given process instance and
   *          compliant to the given query. May return null in
   *          case no such external task exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one external task is delivered by the underlying
   *          query.
   */
  public static ExternalTask externalTask(ExternalTaskQuery externalTaskQuery, ProcessInstance processInstance) {
    return assertThat(processInstance).isNotNull().externalTask(externalTaskQuery).getActual();
  }

  /**
   * Helper method to easily access the process definition
   * on which the last asserted process instance is based.
   *
   * @return  the process definition on which the last
   *          asserted process instance is based.
   * @throws  java.lang.IllegalStateException in case no
   *          process instance was asserted yet.
   */
  public static ProcessDefinition processDefinition() {
    ProcessInstanceAssert lastAssert = AbstractProcessAssert.getLastAssert(ProcessInstanceAssert.class);
    if (lastAssert == null)
      throw new IllegalStateException(
        "Call a process instance assertion first - " +
          "e.g. assertThat(processInstance)... !"
      );
    return processDefinition(lastAssert.getActual());
  }

  /**
   * Helper method to easily access the process definition
   * on which the given process instance is based.
   *
   * @param   processInstance the process instance for which
   *          the definition should be retrieved.
   * @return  the process definition on which the given
   *          process instance is based.
   */
  public static ProcessDefinition processDefinition(ProcessInstance processInstance) {
    assertThat(processInstance).isNotNull();
    return processDefinition(processDefinitionQuery().processDefinitionId(processInstance.getProcessDefinitionId()));
  }

  /**
   * Helper method to easily access the process definition with the
   * given processDefinitionKey.
   *
   * @param   processDefinitionKey the key of the process definition
   *          that should be retrieved.
   * @return  the process definition with the given key.
   *          May return null if no such process definition exists.
   */
  public static ProcessDefinition processDefinition(String processDefinitionKey) {
    Assertions.assertThat(processDefinitionKey).isNotNull();
    return processDefinition(processDefinitionQuery().processDefinitionKey(processDefinitionKey));
  }

  /**
   * Helper method to easily access the process definition compliant
   * to a given process definition query.
   *
   * @param   processDefinitionQuery the query with which the process
   *          definition should be retrieved.
   * @return  the process definition compliant to the given query. May
   *          return null in case no such process definition exists.
   * @throws  org.camunda.bpm.engine.ProcessEngineException in case more
   *          than one process definition is delivered by the underlying
   *          query.
   */
  public static ProcessDefinition processDefinition(ProcessDefinitionQuery processDefinitionQuery) {
    return processDefinitionQuery.singleResult();
  }

  /**
   * Helper method to easily access the only called process instance
   * currently available in the context of the last asserted process
   * instance.
   *
   * @return  the only called process instance called by the last asserted process
   *          instance. May return null if no such process instance exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one process instance is delivered by the underlying
   *          query or in case no process instance was asserted
   *          yet.
   */
  public static ProcessInstance calledProcessInstance() {
    return calledProcessInstance(processInstanceQuery());
  }

  /**
   * Helper method to easily access the only called process instance
   * currently available in the context of the given process instance.
   *
   * @param   processInstance the process instance for which
   *          a called process instance should be retrieved.
   * @return  the only called process instance called by the given process
   *          instance. May return null if no such process instance exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one process instance is delivered by the underlying
   *          query.
   */
  public static ProcessInstance calledProcessInstance(ProcessInstance processInstance) {
    return calledProcessInstance(processInstanceQuery(), processInstance);
  }

  /**
   * Helper method to easily access the only called process instance with
   * the given processDefinitionKey currently available in the context
   * of the last asserted process instance.
   *
   * @param   processDefinitionKey the key of the process instance that should
   *          be retrieved.
   * @return  the only such process instance called by the last asserted process
   *          instance. May return null if no such process instance exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one process instance is delivered by the underlying
   *          query or in case no process instance was asserted
   *          yet.
   */
  public static ProcessInstance calledProcessInstance(String processDefinitionKey) {
    Assertions.assertThat(processDefinitionKey).isNotNull();
    return calledProcessInstance(processInstanceQuery().processDefinitionKey(processDefinitionKey));
  }

  /**
   * Helper method to easily access the only called process instance with the
   * given processDefinitionKey currently available in the context
   * of the given process instance.
   *
   * @param   processDefinitionKey the key of the process instance that should
   *          be retrieved.
   * @param   processInstance the process instance for which
   *          a called process instance should be retrieved.
   * @return  the only such process instance called by the given process instance.
   *          May return null if no such process instance exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one process instance is delivered by the underlying
   *          query.
   */
  public static ProcessInstance calledProcessInstance(String processDefinitionKey, ProcessInstance processInstance) {
    Assertions.assertThat(processDefinitionKey).isNotNull();
    return calledProcessInstance(processInstanceQuery().processDefinitionKey(processDefinitionKey), processInstance);
  }

  /**
   * Helper method to easily access the only called process instance compliant to
   * a given processInstanceQuery and currently available in the context
   * of the last asserted process instance.
   *
   * @param   processInstanceQuery the query with which the called process instance should
   *          be retrieved. This query will be further narrowed to the last asserted
   *          process instance.
   * @return  the only such process instance called by the last asserted process instance and
   *          compliant to the given query. May return null in case no such task exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one process instance is delivered by the underlying query or in case no
   *          process instance was asserted yet.
   */
  public static ProcessInstance calledProcessInstance(ProcessInstanceQuery processInstanceQuery) {
    ProcessInstanceAssert lastAssert = AbstractProcessAssert.getLastAssert(ProcessInstanceAssert.class);
    if (lastAssert == null)
      throw new IllegalStateException(
        "Call a process instance assertion first - " +
          "e.g. assertThat(processInstance)... !"
      );
    return calledProcessInstance(processInstanceQuery, lastAssert.getActual());
  }

  /**
   * Helper method to easily access the only called process instance compliant to
   * a given processInstanceQuery and currently available in the context of the given
   * process instance.
   *
   * @param   processInstanceQuery the query with which the process instance should
   *          be retrieved. This query will be further narrowed to the given process
   *          instance.
   * @param   processInstance the process instance for which
   *          a called process instance should be retrieved.
   * @return  the only such process instance called by the given process instance and
   *          compliant to the given query. May return null in
   *          case no such process instance exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one instance is delivered by the underlying
   *          query.
   */
  public static ProcessInstance calledProcessInstance(ProcessInstanceQuery processInstanceQuery, ProcessInstance processInstance) {
    return assertThat(processInstance).isNotNull().calledProcessInstance(processInstanceQuery).getActual();
  }

  /**
   * Helper method to easily access the only job currently
   * available in the context of the last asserted process
   * instance.
   *
   * @return  the only job of the last asserted process
   *          instance. May return null if no such job exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one job is delivered by the underlying
   *          query or in case no process instance was asserted
   *          yet.
   */
  public static Job job() {
    return job(jobQuery());
  }

  /**
   * Helper method to easily access the only job currently
   * available in the context of the given process instance.
   *
   * @param   processInstance the process instance for which
   *          a job should be retrieved.
   * @return  the only job of the process instance. May
   *          return null if no such task exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one job is delivered by the underlying
   *          query.
   */
  public static Job job(ProcessInstance processInstance) {
    return job(jobQuery(), processInstance);
  }

  /**
   * Helper method to easily access the only job with the
   * given activityId currently available in the context
   * of the last asserted process instance.
   *
   * @param   activityId the id of the job that should
   *          be retrieved.
   * @return  the only job of the last asserted process
   *          instance. May return null if no such job exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one job is delivered by the underlying
   *          query or in case no process instance was asserted
   *          yet.
   */
  public static Job job(String activityId) {
    ProcessInstanceAssert lastAssert = AbstractProcessAssert.getLastAssert(ProcessInstanceAssert.class);
    if (lastAssert == null)
      throw new IllegalStateException(
        "Call a process instance assertion first - " +
          "e.g. assertThat(processInstance)... !"
      );
    return job(activityId, lastAssert.getActual());
  }

  /**
   * Helper method to easily access the only job with the
   * given activityId currently available in the context
   * of the given process instance.
   *
   * @param   activityId the activityId of the job that should
   *          be retrieved.
   * @param   processInstance the process instance for which
   *          a job should be retrieved.
   * @return  the only job of the given process instance. May
   *          return null if no such job exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one job is delivered by the underlying
   *          query.
   */
  public static Job job(String activityId, ProcessInstance processInstance) {
    return assertThat(processInstance).isNotNull().job(activityId).getActual();
  }

  /**
   * Helper method to easily access the only job compliant to
   * a given jobQuery and currently available in the context
   * of the last asserted process instance.
   *
   * @param   jobQuery the query with which the job should
   *          be retrieved. This query will be further narrowed
   *          to the last asserted process instance.
   * @return  the only job of the last asserted process instance
   *          and compliant to the given query. May return null
   *          in case no such task exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one job is delivered by the underlying
   *          query or in case no process instance was asserted
   *          yet.
   */
  public static Job job(JobQuery jobQuery) {
    ProcessInstanceAssert lastAssert = AbstractProcessAssert.getLastAssert(ProcessInstanceAssert.class);
    if (lastAssert == null)
      throw new IllegalStateException(
        "Call a process instance assertion first - " +
          "e.g. assertThat(processInstance)... !"
      );
    return job(jobQuery, lastAssert.getActual());
  }

  /**
   * Helper method to easily access the only job compliant to
   * a given jobQuery and currently available in the context
   * of the given process instance.
   *
   * @param   jobQuery the query with which the job should
   *          be retrieved. This query will be further narrowed
   *          to the given process instance.
   * @param   processInstance the process instance for which
   *          a job should be retrieved.
   * @return  the only job of the given process instance and
   *          compliant to the given query. May return null in
   *          case no such job exists.
   * @throws  java.lang.IllegalStateException in case more
   *          than one job is delivered by the underlying
   *          query.
   */
  public static Job job(JobQuery jobQuery, ProcessInstance processInstance) {
    return assertThat(processInstance).isNotNull().job(jobQuery).getActual();
  }

  /**
   * Helper method to easily claim a task for a specific
   * assignee.
   *
   * @param   task Task to be claimed for an assignee
   * @param   assigneeUserId userId of assignee for which
   *          the task should be claimed
   * @return  the assigned task - properly refreshed to its
   *          assigned state.
   */
  public static Task claim(Task task, String assigneeUserId) {
    if (task == null || assigneeUserId == null)
      throw new IllegalArgumentException(format("Illegal call " +
        "of claim(task = '%s', assigneeUserId = '%s') - both must " +
        "not be null!", task, assigneeUserId));
    taskService().claim(task.getId(), assigneeUserId);
    return taskQuery().taskId(task.getId()).singleResult();
  }

  /**
   * Helper method to easily unclaim a task.
   *
   * @param   task Task to be claimed for an assignee
   * @return  the assigned task - properly refreshed to its
   *          unassigned state.
   */
  public static Task unclaim(Task task) {
    if (task == null)
      throw new IllegalArgumentException(format("Illegal call " +
        "of unclaim(task = '%s') - task must " +
        "not be null!", task));
    taskService().claim(task.getId(), null);
    return taskQuery().taskId(task.getId()).singleResult();
  }

  /**
   * Helper method to easily complete a task and pass some
   * process variables.
   *
   * @param   task Task to be completed
   * @param   variables Process variables to be passed to the
   *          process instance when completing the task. For
   *          setting those variables, you can use
   *          withVariables(String key, Object value, ...)
   */
  public static void complete(Task task, Map<String, Object> variables) {
    if (task == null || variables == null)
      throw new IllegalArgumentException(format("Illegal call of complete(task = '%s', variables = '%s') - both must not be null!", task, variables));
    taskService().complete(task.getId(), variables);
  }

  /**
   * Helper method to easily complete a task.
   *
   * @param   task Task to be completed
   */
  public static void complete(Task task) {
    if (task == null)
      throw new IllegalArgumentException("Illegal call of complete(task = 'null') - must not be null!");
    taskService().complete(task.getId());
  }

  /**
   * Helper method to easily fetch, lock and complete an external task.<p>
   * Note: if multiple external tasks exist that can be locked for the topic of
   * the given external task, this method might throw an
   * {@link IllegalStateException} if an external task with a different id is
   * locked by chance. In this case, it is more advisable to use the
   * {@link #fetchAndLock(String, String, int) fetchAndLock} and
   * {@link #complete(LockedExternalTask)} methods to achieve reliable results.
   *
   * @param externalTask
   *          External task to be completed
   */
  public static void complete(ExternalTask externalTask) {
    if (externalTask == null) {
      throw new IllegalArgumentException("Illegal call of completeExternalTask(externalTask = 'null') - must not be null!");
    }
    complete(externalTask, Collections.<String, Object>emptyMap());
  }

  /**
   * Helper method to easily fetch, lock and complete an external task.<p>
   * Note: if multiple external tasks exist that can be locked for the topic of
   * the given external task, this method might throw an
   * {@link IllegalStateException} if an external task with a different id is
   * locked by chance. In this case, it is more advisable to use the
   * {@link #fetchAndLock(String, String, int) fetchAndLock} and
   * {@link #complete(LockedExternalTask, Map)} methods to achieve reliable results.
   *
   * @param externalTask
   *          External task to be completed
   * @param variables
   *          Process variables to be passed to the process instance when
   *          completing the task. For setting those variables, you can use
   *          withVariables(String key, Object value, ...)
   */
  public static void complete(ExternalTask externalTask, Map<String, Object> variables) {
    if (externalTask == null || variables == null) {
      throw new IllegalArgumentException(format("Illegal call of completeExternalTask(externalTask = '%s', variables = '%s') - both must not be null!", externalTask, variables));
    }
    List<LockedExternalTask> lockedTasks = fetchAndLock(externalTask.getTopicName(), DEFAULT_WORKER_EXTERNAL_TASK, 1);
    if (lockedTasks.isEmpty()) {
      throw new NotFoundException(format("No lockable external task found for externalTask = '%s', variables = '%s'", externalTask, variables));
    }
    if (!lockedTasks.get(0).getId().equals(externalTask.getId())) {
      throw new IllegalStateException(format("Multiple external tasks found for externalTask = '%s', variables = '%s'", externalTask, variables));
    }
    complete(lockedTasks.get(0), variables);
  }

  /**
   * Helper method to easily fetch and lock external tasks from a given topic
   * using a given workerId. The tasks will be locked for
   * {@link #DEFAULT_LOCK_DURATION_EXTERNAL_TASK} milliseconds.
   *
   * @param topic
   *          the name of the topic to query external tasks from
   * @param workerId
   *          the id of the worker to lock the tasks for
   * @param maxResults
   *          the maximum number of tasks to return
   * @return list of external tasks locked for the given workerId
   */
  public static List<LockedExternalTask> fetchAndLock(String topic, String workerId, int maxResults) {
    if (workerId == null || topic == null) {
      throw new IllegalArgumentException(format("Illegal call of fetchAndLock(topic = '%s', workerId = '%s', maxResults = '%s') - all must not be null!", workerId, topic, maxResults));
    }
    return externalTaskService().fetchAndLock(maxResults, workerId)
      .topic(topic, DEFAULT_LOCK_DURATION_EXTERNAL_TASK)
      .execute();
  }

  /**
   * Helper method to easily complete a locked external task.
   *
   * @param lockedExternalTask
   *          an external task that was locked using the
   *          {@link #fetchAndLock(String, String, int) fetchAndLock} method
   */
  public static void complete(LockedExternalTask lockedExternalTask) {
    if (lockedExternalTask == null) {
      throw new IllegalArgumentException("Illegal call of completeExternalTask(lockedExternalTask = 'null') - must not be null!");
    }
    complete(lockedExternalTask, Collections.<String, Object>emptyMap());
  }

  /**
   * Helper method to easily complete a locked external task.
   *
   * @param lockedExternalTask
   *          an external task that was locked using the
   *          {@link #fetchAndLock(String, String, int) fetchAndLock} method
   * @param variables
   *          Process variables to be passed to the process instance when
   *          completing the task. For setting those variables, you can use
   *          withVariables(String key, Object value, ...)
   */
  public static void complete(LockedExternalTask lockedExternalTask, Map<String, Object> variables) {
    if (lockedExternalTask == null || variables == null) {
      throw new IllegalArgumentException(format("Illegal call of completeExternalTask(lockedExternalTask = '%s', variables = '%s') - both must not be null!", lockedExternalTask, variables));
    }
    externalTaskService().complete(lockedExternalTask.getId(), lockedExternalTask.getWorkerId(), variables);
  }

  /**
   * Helper method to easily execute a job.
   *
   * @param   job Job to be executed.
   */
  public static void execute(Job job) {
    if (job == null)
      throw new IllegalArgumentException(format("Illegal call of execute(job = '%s') - must not be null!", job));
    Job current = jobQuery().jobId(job.getId()).singleResult();
    if (current == null)
      throw new IllegalStateException(format("Illegal state when calling execute(job = '%s') - job does not exist anymore!", job));
    managementService().executeJob(job.getId());
  }

  /**
   * Maps any element (task, event, gateway) from the name to the ID.
   *
   * @param name
   * @return the ID of the element
   */
  public static String findId(String name) {
    if (name == null) {
      throw new IllegalArgumentException("Illegal call of findId(name = 'null') - must not be null!");
    }
    Map<String, String> nameToIDMapping = new HashMap<>();
    // find deployed process models
    List<ProcessDefinition> processDefinitions = repositoryService()
        .createProcessDefinitionQuery()
        .orderByProcessDefinitionVersion().asc()
        .list();
    // parse process models
    for (ProcessDefinition processDefinition : processDefinitions) {
      BpmnModelInstance bpmnModelInstance = repositoryService().getBpmnModelInstance(processDefinition.getId());
      Collection<Activity> activities = bpmnModelInstance.getModelElementsByType(Activity.class);
      for (Activity activity: activities) {
        insertAndCheckForDuplicateNames(nameToIDMapping, activity.getName(), activity.getId());
      }
      Collection<Event> events = bpmnModelInstance.getModelElementsByType(Event.class);
      for (Event event : events) {
        insertAndCheckForDuplicateNames(nameToIDMapping, event.getName(), event.getId());
      }
      Collection<Gateway> gateways = bpmnModelInstance.getModelElementsByType(Gateway.class);
      for (Gateway gateway : gateways) {
        insertAndCheckForDuplicateNames(nameToIDMapping, gateway.getName(), gateway.getId());
       }
    }
    // look for name and return ID
    Assertions.assertThat(nameToIDMapping.containsKey(name))
      .overridingErrorMessage("Element with name '%s' doesn't exist", name)
      .isTrue();
    Assertions.assertThat(nameToIDMapping.get(name))
      .overridingErrorMessage("Name '%s' is not unique", name)
      .isNotEqualTo(DUPLICATED_NAME);
    return nameToIDMapping.get(name);
  }

  private static void insertAndCheckForDuplicateNames(Map<String, String> nameToIDMapping, String name, String id) {
    if (nameToIDMapping.containsKey(name)) {
      if (nameToIDMapping.get(name).equals(id)) {
        // already inserted as diagram includes two pools
      } else {
        nameToIDMapping.put(name, DUPLICATED_NAME);
      }
    } else {
      nameToIDMapping.put(name, id);
    }
  }
}


text:
namespace boost {

namespace sync  {

namespace detail {

namespace mach {

class basic_semaphore
{
    BOOST_DELETED_FUNCTION(basic_semaphore(basic_semaphore const&))
    BOOST_DELETED_FUNCTION(basic_semaphore& operator=(basic_semaphore const&))

public:
    explicit basic_semaphore(unsigned int i = 0)
    {
        kern_return_t result = semaphore_create(mach_task_self(), &m_sem, SYNC_POLICY_FIFO, i);
        if (result != KERN_SUCCESS)
            BOOST_SYNC_DETAIL_THROW(resource_error, (sync::detail::system_ns::errc::not_enough_memory)("semaphore constructor failed in semaphore_create"));
    }

    ~basic_semaphore()
    {
        BOOST_VERIFY(semaphore_destroy(mach_task_self(), m_sem) == KERN_SUCCESS);
    }

    void post()
    {
        BOOST_VERIFY(semaphore_signal(m_sem) == KERN_SUCCESS);
    }

    void post_all()
    {
        BOOST_VERIFY(semaphore_signal_all(m_sem) == KERN_SUCCESS);
    }

    void wait()
    {
        kern_return_t result = semaphore_wait(m_sem);
        if (BOOST_UNLIKELY(result != KERN_SUCCESS))
        {
            switch (result)
            {
            case KERN_INVALID_ARGUMENT:
                BOOST_SYNC_DETAIL_THROW(wait_error, (sync::detail::system_ns::errc::invalid_argument)("semaphore::wait failed: the specified semaphore is invalid."));

            case KERN_TERMINATED:
                BOOST_SYNC_DETAIL_THROW(wait_error, (sync::detail::system_ns::errc::invalid_argument)("semaphore::wait failed: the specified semaphore has been destroyed"));

            case KERN_ABORTED:
            default:
                BOOST_SYNC_DETAIL_THROW(wait_error, (sync::detail::system_ns::errc::operation_canceled)("semaphore::wait failed: the wait operation has been aborted"));
            }
        }
    }

    bool try_wait()
    {
        const mach_timespec_t wait_time = { 0, 0 };
        return priv_timed_wait(wait_time);
    }

    bool timed_wait(sync::detail::system_duration dur)
    {
        sync::detail::system_duration::native_type time_left = dur.get();
        if (time_left < 0)
            time_left = 0;
        sync::detail::system_duration::native_type time_left_sec = time_left / sync::detail::system_duration::subsecond_fraction;
        sync::detail::system_duration::native_type time_left_subsec = time_left % sync::detail::system_duration::subsecond_fraction;

        enum
        {
            nanoseconds_fraction = 1000000000u,
            conversion_ratio = static_cast< uint64_t >(nanoseconds_fraction) >= sync::detail::system_duration::subsecond_fraction ?
                nanoseconds_fraction / sync::detail::system_duration::subsecond_fraction :
                sync::detail::system_duration::subsecond_fraction / nanoseconds_fraction
        };

        const mach_timespec_t wait_time =
        {
            static_cast< unsigned int >( time_left_sec ),
            static_cast< uint64_t >( nanoseconds_fraction ) >= sync::detail::system_duration::subsecond_fraction ?
                static_cast< clock_res_t >( time_left_subsec / conversion_ratio)
              : static_cast< clock_res_t >( time_left_subsec * conversion_ratio)
        };

        return priv_timed_wait(wait_time);
    }

    bool timed_wait(sync::detail::system_time_point const& t)
    {
        return timed_wait(t - sync::detail::system_time_point::now());
    }

    template< typename TimePoint >
    bool timed_wait(sync::detail::chrono_time_point< TimePoint > const& t)
    {
        typedef TimePoint time_point;
        typedef typename time_point::clock clock;
        typedef typename time_point::duration duration;
        time_point now = clock::now();
        while (now < t.get())
        {
            if (timed_wait(sync::detail::time_traits< duration >::to_sync_unit(t.get() - now)))
                return true;
            now = clock::now();
        }
        return false;
    }

private:
    bool priv_timed_wait(const mach_timespec_t& wait_time)
    {
        kern_return_t result = semaphore_timedwait(m_sem, wait_time);

        if (result == KERN_SUCCESS)
            return true;

        if (BOOST_UNLIKELY(result != KERN_OPERATION_TIMED_OUT))
        {
            switch (result)
            {
            case KERN_INVALID_ARGUMENT:
                BOOST_SYNC_DETAIL_THROW(wait_error, (sync::detail::system_ns::errc::invalid_argument)("semaphore::timed_wait failed: the specified semaphore is invalid."));

            case KERN_TERMINATED:
                BOOST_SYNC_DETAIL_THROW(wait_error, (sync::detail::system_ns::errc::invalid_argument)("semaphore::timed_wait failed: the specified semaphore has been destroyed"));

            case KERN_ABORTED:
            default:
                BOOST_SYNC_DETAIL_THROW(wait_error, (sync::detail::system_ns::errc::operation_canceled)("semaphore::timed_wait failed: the wait operation has been aborted"));
            }
        }

        return false;
    }

private:
    semaphore_t m_sem;
};

} // namespace mach

} // namespace detail

} // namespace sync

} // namespace boost

#include <boost/sync/detail/footer.hpp>

#endif // BOOST_SYNC_DETAIL_SEMAPHORE_BASIC_SEMAPHORE_MACH_HPP_INCLUDED_

redpajama_set_name: RedPajamaGithub


text:
@interface sparkyAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Nest.Resolvers.Converters;
using Elasticsearch.Net;
using System.Linq.Expressions;

namespace Nest
{

	public class BaseFilter
	{
		[JsonProperty(PropertyName = "bool")]
		internal BoolBaseFilterDescriptor BoolFilterDescriptor { get; set; }

		private static readonly IEnumerable<BaseFilter> Empty = Enumerable.Empty<BaseFilter>();

		[JsonIgnore]
		public virtual bool IsConditionless { get; internal set; }
		[JsonIgnore]
		public bool IsStrict { get; internal set; }
		[JsonIgnore]
		public bool IsVerbatim { get; internal set; }

		/// <summary>
		/// AND's two BaseFilters
		/// </summary>
		/// <returns>A new basefilter that represents the AND of the two</returns>
		public static BaseFilter operator &(BaseFilter leftFilter, BaseFilter rightFilter)
		{
			var defaultFilter = new BaseFilter() { IsConditionless = true };
			leftFilter = leftFilter ?? defaultFilter;
			rightFilter = rightFilter ?? defaultFilter;
			var combined = new[] { leftFilter, rightFilter };

			//if any of the queries is conditionless return the first one that is not
			//or return the defaultQuery
			if (combined.Any(bf => bf.IsConditionless))
				return combined.FirstOrDefault(bf=>!bf.IsConditionless) ?? defaultFilter;

			//return simple combination of the two if merging is not possible/necessary
			var noMergeFilter = CombineIfNoMergeIsNecessary(leftFilter, rightFilter, combined);
			if (noMergeFilter != null)
				return noMergeFilter;

			//if the left is a strict bool try to merge right on left first
			var joinStrictLeft = StrictSingleSideAndMerge(leftFilter, rightFilter);
			if (joinStrictLeft != null)
				return joinStrictLeft;

			// if the right side is a strict bool try to merge left on right
			var joinStrictRight = StrictSingleSideAndMerge(rightFilter, leftFilter);
			if (joinStrictRight != null)
				return joinStrictRight;

			// if the left side is a normal bool try to merge right on left
			var joinLeft = SingleSideAndMerge(leftFilter, rightFilter);
			if (joinLeft != null)
				return joinLeft;

			// if the right side is a normal bool try to merge lefft on right
			var joinRight = SingleSideAndMerge(rightFilter, leftFilter);
			return joinRight ?? defaultFilter;
		}

		public static BaseFilter operator |(BaseFilter leftFilter, BaseFilter rightFilter)
		{
			var defaultFilter = new BaseFilter() { IsConditionless = true };
			leftFilter = leftFilter ?? defaultFilter;
			rightFilter = rightFilter ?? defaultFilter;
			var combined = new[] { leftFilter, rightFilter };

			if (combined.Any(bf => bf.IsConditionless))
				return combined.FirstOrDefault(bf => !bf.IsConditionless) ?? defaultFilter;

			var leftBoolFilter = leftFilter.BoolFilterDescriptor;
			var rightBoolFilter = rightFilter.BoolFilterDescriptor;

			var f = new BaseFilter();
			var fq = new BoolBaseFilterDescriptor();
			fq._ShouldFilters = new[] { leftFilter, rightFilter };
			f.BoolFilterDescriptor = fq;

			//if neither the left nor the right side represent a bool filter join them
			if (leftFilter.BoolFilterDescriptor == null && rightFilter.BoolFilterDescriptor == null)
			{
				fq._ShouldFilters = leftFilter.MergeShouldFilters(rightFilter);
				return f;
			}
			//if the left or right sight already is a bool filter determine join the non bool query side of the
			//of the operation onto the other.
			if (leftFilter.BoolFilterDescriptor != null && rightFilter.BoolFilterDescriptor == null && !leftFilter.IsStrict)
			{
				JoinShouldOnSide(leftFilter, rightFilter, fq);
			}
			else if (rightFilter.BoolFilterDescriptor != null && leftFilter.BoolFilterDescriptor == null && !rightFilter.IsStrict)
			{
				JoinShouldOnSide(rightFilter, leftFilter, fq);
			}
			//both sides already represent a bool filter
			else
			{
				//both sides report that we may merge the shoulds
				if (!leftFilter.IsStrict && !rightFilter.IsStrict
					&& leftBoolFilter.CanJoinShould()
					&& rightBoolFilter.CanJoinShould())
					fq._ShouldFilters = leftFilter.MergeShouldFilters(rightFilter);
				else
					//create a new nested bool with two separate should bool sections
					fq._ShouldFilters = new[] { leftFilter, rightFilter };
			}
			return f;
		}

		public static BaseFilter operator !(BaseFilter lbq)
		{
			if (lbq == null || lbq.IsConditionless)
				return new BaseFilter { IsConditionless = true };

			var f = new BaseFilter();
			var fq = new BoolBaseFilterDescriptor();
			fq._MustNotFilters = new[] { lbq };

			f.BoolFilterDescriptor = fq;
			return f;
		}

		public static bool operator false(BaseFilter a)
		{
			return false;
		}

		public static bool operator true(BaseFilter a)
		{
			return false;
		}

		private static void JoinShouldOnSide(BaseFilter lbq, BaseFilter rbq, BoolBaseFilterDescriptor bq)
		{
			bq._ShouldFilters = lbq.MergeShouldFilters(rbq);
		}

		private static BaseFilter CombineIfNoMergeIsNecessary(
			BaseFilter leftFilter,
			BaseFilter rightFilter,
			BaseFilter[] combined)
		{
			var leftBoolFilter = leftFilter.BoolFilterDescriptor;
			var rightBoolFilter = rightFilter.BoolFilterDescriptor;
			//if neither side is already a boolfilter
			//  or if all boolfilters are strict.
			//  or if one side is strict and the other is null
			//no merging is needed just return the combination
			if (
				(leftBoolFilter == null && rightBoolFilter == null)
				|| (leftFilter.IsStrict && rightFilter.IsStrict)
				|| (leftFilter.IsStrict && rightBoolFilter == null)
				|| (rightFilter.IsStrict && leftBoolFilter == null))
			{
				return CreateReturnFilter((returnFilter, returnBoolFilter) => returnBoolFilter._MustFilters = combined);
			}
			return null;
		}

		private static BaseFilter StrictSingleSideAndMerge(BaseFilter targetFilter, BaseFilter mergeFilter)
		{
			//if the target is not strict return
			if (!targetFilter.IsStrict) return null;

			var mergeBoolFilter = mergeFilter.BoolFilterDescriptor;

			return CreateReturnFilter((returnFilter, returnBoolFilter) =>
			{
				if (mergeBoolFilter._MustNotFilters.HasAny())
				{
					returnBoolFilter._MustNotFilters = mergeBoolFilter._MustNotFilters;
					mergeBoolFilter._MustNotFilters = null;
				}

				returnBoolFilter._MustFilters = new[] { targetFilter }.Concat(mergeBoolFilter._MustFilters ?? Empty);
			});
		}

		private static BaseFilter SingleSideAndMerge(BaseFilter targetFilter, BaseFilter mergeFilter)
		{
			var targetBoolFilter = targetFilter.BoolFilterDescriptor;
			var mergeBoolFilter = mergeFilter.BoolFilterDescriptor;

			if (targetBoolFilter == null) return null;

			var combined = new[] { targetFilter, mergeFilter };
			return CreateReturnFilter((returnFilter, returnBoolFilter) =>
			{
				if (!targetBoolFilter.CanMergeMustAndMustNots() || !mergeBoolFilter.CanMergeMustAndMustNots())
				{
					returnBoolFilter._MustFilters = combined;
					return;
				}

				returnBoolFilter._MustFilters = (targetBoolFilter._MustFilters ?? Empty)
					.Concat(mergeBoolFilter != null
						? (mergeBoolFilter._MustFilters ?? Empty)
						: new[] {mergeFilter})
					.NullIfEmpty();
				returnBoolFilter._MustNotFilters = (targetBoolFilter._MustNotFilters ?? Empty)
					.Concat(mergeBoolFilter != null
						? (mergeBoolFilter._MustNotFilters ?? Empty)
						: Empty
					).NullIfEmpty();

			});
		}

		public static BaseFilter CreateReturnFilter(Action<BaseFilter, BoolBaseFilterDescriptor> modify = null)
		{
			var returnFilter = new BaseFilter();
			var returnBoolFilter = new BoolBaseFilterDescriptor() { };
			returnFilter.BoolFilterDescriptor = returnBoolFilter;
			if (modify != null)
			{
				modify(returnFilter, returnBoolFilter);
			}
			return returnFilter;
		}

	}
}


text:
#ifndef GrAtlasTextBlob_DEFINED
#define GrAtlasTextBlob_DEFINED

#include "GrBatchAtlas.h"
#include "GrBatchFontCache.h"
#include "GrColor.h"
#include "GrMemoryPool.h"
#include "SkDescriptor.h"
#include "SkMaskFilter.h"
#include "SkSurfaceProps.h"
#include "SkTInternalLList.h"

class GrBlobRegenHelper;
struct GrDistanceFieldAdjustTable;
class GrMemoryPool;
class SkDrawFilter;
class SkTextBlob;
class SkTextBlobRunIterator;

// With this flag enabled, the GrAtlasTextContext will, as a sanity check, regenerate every blob
// that comes in to verify the integrity of its cache
#define CACHE_SANITY_CHECK 0

/*
 * A GrAtlasTextBlob contains a fully processed SkTextBlob, suitable for nearly immediate drawing
 * on the GPU.  These are initially created with valid positions and colors, but invalid
 * texture coordinates.  The GrAtlasTextBlob itself has a few Blob-wide properties, and also
 * consists of a number of runs.  Runs inside a blob are flushed individually so they can be
 * reordered.
 *
 * The only thing(aside from a memcopy) required to flush a GrAtlasTextBlob is to ensure that
 * the GrAtlas will not evict anything the Blob needs.
 *
 * Note: This struct should really be named GrCachedAtasTextBlob, but that is too verbose.
 *
 * *WARNING* If you add new fields to this struct, then you may need to to update AssertEqual
 */
class GrAtlasTextBlob : public SkNVRefCnt<GrAtlasTextBlob> {
public:
    SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrAtlasTextBlob);

    static GrAtlasTextBlob* Create(GrMemoryPool* pool, int glyphCount, int runCount);

    struct Key {
        Key() {
            sk_bzero(this, sizeof(Key));
        }
        uint32_t fUniqueID;
        // Color may affect the gamma of the mask we generate, but in a fairly limited way.
        // Each color is assigned to on of a fixed number of buckets based on its
        // luminance. For each luminance bucket there is a "canonical color" that
        // represents the bucket.  This functionality is currently only supported for A8
        SkColor fCanonicalColor;
        SkPaint::Style fStyle;
        SkPixelGeometry fPixelGeometry;
        bool fHasBlur;

        bool operator==(const Key& other) const {
            return 0 == memcmp(this, &other, sizeof(Key));
        }
    };

    void setupKey(const GrAtlasTextBlob::Key& key,
                  const SkMaskFilter::BlurRec& blurRec,
                  const SkPaint& paint) {
        fKey = key;
        if (key.fHasBlur) {
            fBlurRec = blurRec;
        }
        if (key.fStyle != SkPaint::kFill_Style) {
            fStrokeInfo.fFrameWidth = paint.getStrokeWidth();
            fStrokeInfo.fMiterLimit = paint.getStrokeMiter();
            fStrokeInfo.fJoin = paint.getStrokeJoin();
        }
    }

    static const Key& GetKey(const GrAtlasTextBlob& blob) {
        return blob.fKey;
    }

    static uint32_t Hash(const Key& key) {
        return SkChecksum::Murmur3(&key, sizeof(Key));
    }

    void operator delete(void* p) {
        GrAtlasTextBlob* blob = reinterpret_cast<GrAtlasTextBlob*>(p);
        blob->fPool->release(p);
    }
    void* operator new(size_t) {
        SkFAIL("All blobs are created by placement new.");
        return sk_malloc_throw(0);
    }

    void* operator new(size_t, void* p) { return p; }
    void operator delete(void* target, void* placement) {
        ::operator delete(target, placement);
    }

    bool hasDistanceField() const { return SkToBool(fTextType & kHasDistanceField_TextType); }
    bool hasBitmap() const { return SkToBool(fTextType & kHasBitmap_TextType); }
    void setHasDistanceField() { fTextType |= kHasDistanceField_TextType; }
    void setHasBitmap() { fTextType |= kHasBitmap_TextType; }

    int runCount() const { return fRunCount; }

    void push_back_run(int currRun) {
        SkASSERT(currRun < fRunCount);
        if (currRun > 0) {
            Run::SubRunInfo& newRun = fRuns[currRun].fSubRunInfo.back();
            Run::SubRunInfo& lastRun = fRuns[currRun - 1].fSubRunInfo.back();
            newRun.setAsSuccessor(lastRun);
        }
    }

    // sets the last subrun of runIndex to use distance field text
    void setSubRunHasDistanceFields(int runIndex, bool hasLCD) {
        Run& run = fRuns[runIndex];
        Run::SubRunInfo& subRun = run.fSubRunInfo.back();
        subRun.setUseLCDText(hasLCD);
        subRun.setDrawAsDistanceFields();
    }

    void setRunDrawAsPaths(int runIndex) {
        fRuns[runIndex].fDrawAsPaths = true;
    }

    void setMinAndMaxScale(SkScalar scaledMax, SkScalar scaledMin) {
        // we init fMaxMinScale and fMinMaxScale in the constructor
        fMaxMinScale = SkMaxScalar(scaledMax, fMaxMinScale);
        fMinMaxScale = SkMinScalar(scaledMin, fMinMaxScale);
    }

    // inits the override descriptor on the current run.  All following subruns must use this
    // descriptor
    void initOverride(int runIndex) {
        Run& run = fRuns[runIndex];
        // Push back a new subrun to fill and set the override descriptor
        run.push_back();
        run.fOverrideDescriptor.reset(new SkAutoDescriptor);
    }

    SkGlyphCache* setupCache(int runIndex,
                             const SkSurfaceProps& props,
                             uint32_t scalerContextFlags,
                             const SkPaint& skPaint,
                             const SkMatrix* viewMatrix);

    // Appends a glyph to the blob.  If the glyph is too large, the glyph will be appended
    // as a path.
    void appendGlyph(int runIndex,
                     const SkRect& positions,
                     GrColor color,
                     GrBatchTextStrike* strike,
                     GrGlyph* glyph,
                     GrFontScaler* scaler, const SkGlyph& skGlyph,
                     SkScalar x, SkScalar y, SkScalar scale, bool applyVM);

    static size_t GetVertexStride(GrMaskFormat maskFormat) {
        switch (maskFormat) {
            case kA8_GrMaskFormat:
                return kGrayTextVASize;
            case kARGB_GrMaskFormat:
                return kColorTextVASize;
            default:
                return kLCDTextVASize;
        }
    }

    bool mustRegenerate(const SkPaint& paint, GrColor color, const SkMaskFilter::BlurRec& blurRec,
                        const SkMatrix& viewMatrix, SkScalar x, SkScalar y);

    // flush a GrAtlasTextBlob associated with a SkTextBlob
    void flushCached(GrContext* context,
                     GrDrawContext* dc,
                     const SkTextBlob* blob,
                     const SkSurfaceProps& props,
                     const GrDistanceFieldAdjustTable* distanceAdjustTable,
                     const SkPaint& skPaint,
                     const GrPaint& grPaint,
                     SkDrawFilter* drawFilter,
                     const GrClip& clip,
                     const SkMatrix& viewMatrix,
                     const SkIRect& clipBounds,
                     SkScalar x, SkScalar y);

    // flush a throwaway GrAtlasTextBlob *not* associated with an SkTextBlob
    void flushThrowaway(GrContext* context,
                        GrDrawContext* dc,
                        const SkSurfaceProps& props,
                        const GrDistanceFieldAdjustTable* distanceAdjustTable,
                        const SkPaint& skPaint,
                        const GrPaint& grPaint,
                        const GrClip& clip,
                        const SkMatrix& viewMatrix,
                        const SkIRect& clipBounds,
                        SkScalar x, SkScalar y);

    void computeSubRunBounds(SkRect* outBounds, int runIndex, int subRunIndex,
                             const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
        // We don't yet position distance field text on the cpu, so we have to map the vertex bounds
        // into device space.
        // We handle vertex bounds differently for distance field text and bitmap text because
        // the vertex bounds of bitmap text are in device space.  If we are flushing multiple runs
        // from one blob then we are going to pay the price here of mapping the rect for each run.
        const Run& run = fRuns[runIndex];
        const Run::SubRunInfo& subRun = run.fSubRunInfo[subRunIndex];
        *outBounds = subRun.vertexBounds();
        if (subRun.drawAsDistanceFields()) {
            // Distance field text is positioned with the (X,Y) as part of the glyph position,
            // and currently the view matrix is applied on the GPU
            outBounds->offset(x - fInitialX, y - fInitialY);
            viewMatrix.mapRect(outBounds);
        } else {
            // Bitmap text is fully positioned on the CPU, and offset by an (X,Y) translate in
            // device space.
            SkMatrix boundsMatrix = fInitialViewMatrixInverse;

            boundsMatrix.postTranslate(-fInitialX, -fInitialY);

            boundsMatrix.postTranslate(x, y);

            boundsMatrix.postConcat(viewMatrix);
            boundsMatrix.mapRect(outBounds);

            // Due to floating point numerical inaccuracies, we have to round out here
            outBounds->roundOut(outBounds);
        }
    }

    // position + local coord
    static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
    static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof(SkIPoint16);
    static const size_t kLCDTextVASize = kGrayTextVASize;
    static const size_t kMaxVASize = kGrayTextVASize;
    static const int kVerticesPerGlyph = 4;

    static void AssertEqual(const GrAtlasTextBlob&, const GrAtlasTextBlob&);

    // The color here is the GrPaint color, and it is used to determine whether we
    // have to regenerate LCD text blobs.
    // We use this color vs the SkPaint color because it has the colorfilter applied.
    void initReusableBlob(GrColor color, const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
        fPaintColor = color;
        this->setupViewMatrix(viewMatrix, x, y);
    }

    void initThrowawayBlob(const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
        this->setupViewMatrix(viewMatrix, x, y);
    }

    void regenInBatch(GrDrawBatch::Target* target, GrBatchFontCache* fontCache,
                      GrBlobRegenHelper *helper, int run, int subRun, SkGlyphCache** cache,
                      SkTypeface** typeface, GrFontScaler** scaler,
                      const SkDescriptor** desc, size_t vertexStride,
                      const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
                      GrColor color,
                      void** vertices, size_t* byteCount, int* glyphCount);

    const Key& key() const { return fKey; }

    ~GrAtlasTextBlob() {
        for (int i = 0; i < fRunCount; i++) {
            fRuns[i].~Run();
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////
    // Internal test methods
    GrDrawBatch* test_createBatch(int glyphCount, int run, int subRun,
                                  const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
                                  const SkPaint& skPaint, const SkSurfaceProps& props,
                                  const GrDistanceFieldAdjustTable* distanceAdjustTable,
                                  GrBatchFontCache* cache);

private:
    GrAtlasTextBlob()
        : fMaxMinScale(-SK_ScalarMax)
        , fMinMaxScale(SK_ScalarMax)
        , fTextType(0) {}

    void appendLargeGlyph(GrGlyph* glyph, GrFontScaler* scaler, const SkGlyph& skGlyph,
                          SkScalar x, SkScalar y, SkScalar scale, bool applyVM);

    inline void flushRun(GrDrawContext* dc, GrPipelineBuilder* pipelineBuilder,
                         int run, const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
                         const SkPaint& skPaint, const SkSurfaceProps& props,
                         const GrDistanceFieldAdjustTable* distanceAdjustTable,
                         GrBatchFontCache* cache);

    void flushBigGlyphs(GrContext* context, GrDrawContext* dc,
                        const GrClip& clip, const SkPaint& skPaint,
                        const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
                        const SkIRect& clipBounds);

    void flushRunAsPaths(GrContext* context,
                         GrDrawContext* dc,
                         const SkSurfaceProps& props,
                         const SkTextBlobRunIterator& it,
                         const GrClip& clip, const SkPaint& skPaint,
                         SkDrawFilter* drawFilter, const SkMatrix& viewMatrix,
                         const SkIRect& clipBounds, SkScalar x, SkScalar y);

    // This function will only be called when we are generating a blob from scratch. We record the
    // initial view matrix and initial offsets(x,y), because we record vertex bounds relative to
    // these numbers.  When blobs are reused with new matrices, we need to return to model space so
    // we can update the vertex bounds appropriately.
    void setupViewMatrix(const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
        fInitialViewMatrix = viewMatrix;
        if (!viewMatrix.invert(&fInitialViewMatrixInverse)) {
            fInitialViewMatrixInverse = SkMatrix::I();
            SkDebugf("Could not invert viewmatrix\n");
        }
        fInitialX = x;
        fInitialY = y;

        // make sure all initial subruns have the correct VM and X/Y applied
        for (int i = 0; i < fRunCount; i++) {
            fRuns[i].fSubRunInfo[0].init(fInitialViewMatrix, x, y);
        }
    }

    /*
     * Each Run inside of the blob can have its texture coordinates regenerated if required.
     * To determine if regeneration is necessary, fAtlasGeneration is used.  If there have been
     * any evictions inside of the atlas, then we will simply regenerate Runs.  We could track
     * this at a more fine grained level, but its not clear if this is worth it, as evictions
     * should be fairly rare.
     *
     * One additional point, each run can contain glyphs with any of the three mask formats.
     * We call these SubRuns.  Because a subrun must be a contiguous range, we have to create
     * a new subrun each time the mask format changes in a run.  In theory, a run can have as
     * many SubRuns as it has glyphs, ie if a run alternates between color emoji and A8.  In
     * practice, the vast majority of runs have only a single subrun.
     *
     * Finally, for runs where the entire thing is too large for the GrAtlasTextContext to
     * handle, we have a bit to mark the run as flusahable via rendering as paths.  It is worth
     * pointing. It would be a bit expensive to figure out ahead of time whether or not a run
     * can flush in this manner, so we always allocate vertices for the run, regardless of
     * whether or not it is too large.  The benefit of this strategy is that we can always reuse
     * a blob allocation regardless of viewmatrix changes.  We could store positions for these
     * glyphs.  However, its not clear if this is a win because we'd still have to either go the
     * glyph cache to get the path at flush time, or hold onto the path in the cache, which
     * would greatly increase the memory of these cached items.
     */
    struct Run {
        Run()
            : fInitialized(false)
            , fDrawAsPaths(false) {
            // To ensure we always have one subrun, we push back a fresh run here
            fSubRunInfo.push_back();
        }
        struct SubRunInfo {
            SubRunInfo()
                : fAtlasGeneration(GrBatchAtlas::kInvalidAtlasGeneration)
                , fVertexStartIndex(0)
                , fVertexEndIndex(0)
                , fGlyphStartIndex(0)
                , fGlyphEndIndex(0)
                , fColor(GrColor_ILLEGAL)
                , fMaskFormat(kA8_GrMaskFormat)
                , fDrawAsDistanceFields(false)
                , fUseLCDText(false) {
                fVertexBounds.setLargestInverted();
            }
            SubRunInfo(const SubRunInfo& that)
                : fBulkUseToken(that.fBulkUseToken)
                , fStrike(SkSafeRef(that.fStrike.get()))
                , fCurrentViewMatrix(that.fCurrentViewMatrix)
                , fVertexBounds(that.fVertexBounds)
                , fAtlasGeneration(that.fAtlasGeneration)
                , fVertexStartIndex(that.fVertexStartIndex)
                , fVertexEndIndex(that.fVertexEndIndex)
                , fGlyphStartIndex(that.fGlyphStartIndex)
                , fGlyphEndIndex(that.fGlyphEndIndex)
                , fX(that.fX)
                , fY(that.fY)
                , fColor(that.fColor)
                , fMaskFormat(that.fMaskFormat)
                , fDrawAsDistanceFields(that.fDrawAsDistanceFields)
                , fUseLCDText(that.fUseLCDText) {
            }

            // TODO when this object is more internal, drop the privacy
            void resetBulkUseToken() { fBulkUseToken.reset(); }
            GrBatchAtlas::BulkUseTokenUpdater* bulkUseToken() { return &fBulkUseToken; }
            void setStrike(GrBatchTextStrike* strike) { fStrike.reset(SkRef(strike)); }
            GrBatchTextStrike* strike() const { return fStrike.get(); }

            void setAtlasGeneration(uint64_t atlasGeneration) { fAtlasGeneration = atlasGeneration;}
            uint64_t atlasGeneration() const { return fAtlasGeneration; }

            size_t byteCount() const { return fVertexEndIndex - fVertexStartIndex; }
            size_t vertexStartIndex() const { return fVertexStartIndex; }
            size_t vertexEndIndex() const { return fVertexEndIndex; }
            void appendVertices(size_t vertexStride) {
                fVertexEndIndex += vertexStride * kVerticesPerGlyph;
            }

            uint32_t glyphCount() const { return fGlyphEndIndex - fGlyphStartIndex; }
            uint32_t glyphStartIndex() const { return fGlyphStartIndex; }
            uint32_t glyphEndIndex() const { return fGlyphEndIndex; }
            void glyphAppended() { fGlyphEndIndex++; }
            void setColor(GrColor color) { fColor = color; }
            GrColor color() const { return fColor; }
            void setMaskFormat(GrMaskFormat format) { fMaskFormat = format; }
            GrMaskFormat maskFormat() const { return fMaskFormat; }

            void setAsSuccessor(const SubRunInfo& prev) {
                fGlyphStartIndex = prev.glyphEndIndex();
                fGlyphEndIndex = prev.glyphEndIndex();

                fVertexStartIndex = prev.vertexEndIndex();
                fVertexEndIndex = prev.vertexEndIndex();

                // copy over viewmatrix settings
                this->init(prev.fCurrentViewMatrix, prev.fX, prev.fY);
            }

            const SkRect& vertexBounds() const { return fVertexBounds; }
            void joinGlyphBounds(const SkRect& glyphBounds) {
                fVertexBounds.joinNonEmptyArg(glyphBounds);
            }

            void init(const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
                fCurrentViewMatrix = viewMatrix;
                fX = x;
                fY = y;
            }

            // This function assumes the translation will be applied before it is called again
            void computeTranslation(const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
                                    SkScalar*transX, SkScalar* transY);

            // df properties
            void setUseLCDText(bool useLCDText) { fUseLCDText = useLCDText; }
            bool hasUseLCDText() const { return fUseLCDText; }
            void setDrawAsDistanceFields() { fDrawAsDistanceFields = true; }
            bool drawAsDistanceFields() const { return fDrawAsDistanceFields; }

        private:
            GrBatchAtlas::BulkUseTokenUpdater fBulkUseToken;
            SkAutoTUnref<GrBatchTextStrike> fStrike;
            SkMatrix fCurrentViewMatrix;
            SkRect fVertexBounds;
            uint64_t fAtlasGeneration;
            size_t fVertexStartIndex;
            size_t fVertexEndIndex;
            uint32_t fGlyphStartIndex;
            uint32_t fGlyphEndIndex;
            SkScalar fX;
            SkScalar fY;
            GrColor fColor;
            GrMaskFormat fMaskFormat;
            bool fDrawAsDistanceFields; // df property
            bool fUseLCDText; // df property
        };

        SubRunInfo& push_back() {
            // Forward glyph / vertex information to seed the new sub run
            SubRunInfo& newSubRun = fSubRunInfo.push_back();
            const SubRunInfo& prevSubRun = fSubRunInfo.fromBack(1);

            newSubRun.setAsSuccessor(prevSubRun);
            return newSubRun;
        }
        static const int kMinSubRuns = 1;
        SkAutoTUnref<SkTypeface> fTypeface;
        SkSTArray<kMinSubRuns, SubRunInfo> fSubRunInfo;
        SkAutoDescriptor fDescriptor;
        SkScalerContextEffects fEffects;

        // Distance field text cannot draw coloremoji, and so has to fall back.  However,
        // though the distance field text and the coloremoji may share the same run, they
        // will have different descriptors.  If fOverrideDescriptor is non-nullptr, then it
        // will be used in place of the run's descriptor to regen texture coords
        SkAutoTDelete<SkAutoDescriptor> fOverrideDescriptor; // df properties
        bool fInitialized;
        bool fDrawAsPaths;
    };

    template <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs>
    void regenInBatch(GrDrawBatch::Target* target,
                      GrBatchFontCache* fontCache,
                      GrBlobRegenHelper* helper,
                      Run* run, Run::SubRunInfo* info, SkGlyphCache** cache,
                      SkTypeface** typeface, GrFontScaler** scaler,
                      const SkDescriptor** desc,
                      int glyphCount, size_t vertexStride,
                      GrColor color, SkScalar transX,
                      SkScalar transY) const;

    inline GrDrawBatch* createBatch(const Run::SubRunInfo& info,
                                    int glyphCount, int run, int subRun,
                                    const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
                                    GrColor color,
                                    const SkPaint& skPaint, const SkSurfaceProps& props,
                                    const GrDistanceFieldAdjustTable* distanceAdjustTable,
                                    bool useGammaCorrectDistanceTable,
                                    GrBatchFontCache* cache);

    struct BigGlyph {
        BigGlyph(const SkPath& path, SkScalar vx, SkScalar vy, SkScalar scale, bool applyVM)
            : fPath(path)
            , fScale(scale)
            , fX(vx)
            , fY(vy)
            , fApplyVM(applyVM) {}
        SkPath fPath;
        SkScalar fScale;
        SkScalar fX;
        SkScalar fY;
        bool fApplyVM;
    };

    struct StrokeInfo {
        SkScalar fFrameWidth;
        SkScalar fMiterLimit;
        SkPaint::Join fJoin;
    };

    enum TextType {
        kHasDistanceField_TextType = 0x1,
        kHasBitmap_TextType = 0x2,
    };

    // all glyph / vertex offsets are into these pools.
    unsigned char* fVertices;
    GrGlyph** fGlyphs;
    Run* fRuns;
    GrMemoryPool* fPool;
    SkMaskFilter::BlurRec fBlurRec;
    StrokeInfo fStrokeInfo;
    SkTArray<BigGlyph> fBigGlyphs;
    Key fKey;
    SkMatrix fInitialViewMatrix;
    SkMatrix fInitialViewMatrixInverse;
    size_t fSize;
    GrColor fPaintColor;
    SkScalar fInitialX;
    SkScalar fInitialY;

    // We can reuse distance field text, but only if the new viewmatrix would not result in
    // a mip change.  Because there can be multiple runs in a blob, we track the overall
    // maximum minimum scale, and minimum maximum scale, we can support before we need to regen
    SkScalar fMaxMinScale;
    SkScalar fMinMaxScale;
    int fRunCount;
    uint8_t fTextType;
};

#endif


text:
package goclj

import "github.com/cespare/goclj/parse"

func FnFormSymbol(node parse.Node, sym ...string) bool {
	list, ok := node.(*parse.ListNode)
	if !ok {
		return false
	}
	children := list.Children()
	if len(children) == 0 {
		return false
	}
	s, ok := children[0].(*parse.SymbolNode)
	if !ok {
		return false
	}
	if len(sym) == 0 {
		return true
	}
	for _, name := range sym {
		if s.Val == name {
			return true
		}
	}
	return false
}

func FnFormKeyword(node parse.Node, kw ...string) bool {
	list, ok := node.(*parse.ListNode)
	if !ok {
		return false
	}
	children := list.Children()
	if len(children) == 0 {
		return false
	}
	k, ok := children[0].(*parse.KeywordNode)
	if !ok {
		return false
	}
	if len(kw) == 0 {
		return true
	}
	for _, name := range kw {
		if k.Val == name {
			return true
		}
	}
	return false
}

func Symbol(node parse.Node) bool {
	_, ok := node.(*parse.SymbolNode)
	return ok
}

func Newline(node parse.Node) bool {
	_, ok := node.(*parse.NewlineNode)
	return ok
}

func Vector(node parse.Node) bool {
	_, ok := node.(*parse.VectorNode)
	return ok
}

func Keyword(node parse.Node) bool {
	_, ok := node.(*parse.KeywordNode)
	return ok
}

func Comment(node parse.Node) bool {
	_, ok := node.(*parse.CommentNode)
	return ok
}

// Semantic returns whether a node changes the semantics of the code.
// NOTE: right now this is only used for let indenting.
// It might have to be adjusted if used for other purposes.
func Semantic(node parse.Node) bool {
	switch node.(type) {
	case *parse.NewlineNode, *parse.CommentNode, *parse.MetadataNode, *parse.TagNode:
		return false
	}
	return true
}


text:
module TransmissionServer
  attr_accessor :connectors

  def receive_data data
    query = JSON.parse(data)
    case query['command']
      when 'add'
        respond = 'Add: '  + query['uri']
        target = query['client']
        ## Add magnet link to download client
        session = @connectors.find{|client| client.host == target['host'] and client.peer_port == target['port']}
        if session
          session.transmission.add_torrent_by_file(query['uri'])
          session.transmission.add_tracker(query['hash'], 'http://retracker.local/announce') if query['hash']
        end
      when 'move'
        respond = 'move'
        ## Move torrent from download to upload client
      else
        respond = 'Illegal operation'
    end
    puts respond
    send_data respond
    close_connection_after_writing
  end

end


text:
package com.google.ads.googleads.v11.errors;

public interface KeywordPlanCampaignKeywordErrorEnumOrBuilder extends
    // @@protoc_insertion_point(interface_extends:google.ads.googleads.v11.errors.KeywordPlanCampaignKeywordErrorEnum)
    com.google.protobuf.MessageOrBuilder {
}


text:
<?php namespace Pharser\Grammar\Exception;

/**
 * A base exception for all grammar-related exceptions to extend.
 *
 * @author Jack Price <jackprice@outlook.com>
 */
class Exception extends \Exception
{
    //
}


text:
/* TO EVAL CONTENTS: Type evalEditor() in the console. */

// TEST CODE
/*
function test() {
 var x = 1;
 var y = 0;
 var w = 10;
 console.log('test is run x: ' + x);
 console.log('test is run y: ' + y);
 console.log('test is run z: ' + w);
}

// run
test();
*/

// numbers...
// meaningful...
// ?? brackets
// functions } } }
// arrays?
// figures?

// systems have to be able to cope with errors
// lots of programming assumes input is perfect
// think about problems when calling data into question
// solve the problem of... dealing with...

// solve the problem of...
// experience

// house of cards
// malleable
// conversation with material
// process/experience/control/letting-go
// the program isn't something to dominate

/*
var actions = ["Read", "Google", "Forget", "Write", "Question"];
var objects = ["Nesbit", "Sabi", "Focillon", "Herbert", "Phaidon"];
var frequency = ["Again", "Never", "Always", "First", "Second", "Street Number"];
var result = "";

result = actions[Math.floor(Math.random()*actions.length)] + " " +
  objects[Math.floor(Math.random()*objects.length)] + " " +
  frequency[Math.floor(Math.random()*frequency.length)];
console.log(result);
*/

// document.getElementById('dom').innerHTML = 'hiiii';

// I got what I wanted :(

/*var num = words.length;
var times = 0;
for(var i = 0; i < num; i++) {
  for(var j = 0; j < times; j++) {
  	console.log(words[j]);
  }
}*/

/*
var a = document.createElement('a');
a.innerHTML = 'link';
a.setAttribute('href', 'http://www.google.com');
document.getElementById('dom').appendChild(a);
*/
/*
// ACCESS DOM
var mydom = document.getElementById('dom');

// CLEAR DOM
mydom.innerHTML = '';
document.body.setAttribute('style', 'font-family: sans-serif;');

// ADD HEADER
var h1 = document.createElement('h1');
var borderWidth = ---11.01;
var borderStyle = 'border-left: ' + borderWidth + 'px solid red;';
h1.innerHTML = 'My Research Goals';
h1.setAttribute('style', borderStyle);
//a.setAttribute('href', 'http://www.google.com');
mydom.appendChild(h1);

// ADD INPUT PROMPT
var h3 = document.createElement('h3');
var borderWidth = 0.99;
var borderStyle = 'border-left: ' + borderWidth + 'px solid blue;';
h3.innerHTML = 'Goal:';
h3.setAttribute('style', borderStyle);
//a.setAttribute('href', 'http://www.google.com');
mydom.appendChild(h3);

// ADD INPUT PROMPT SUBHEADER
var h4 = document.createElement('label');
var gray = -----1.0009900000000016;
var h4Style = 'color: rgb(' + gray + ',' + gray + ',' + gray + '); font-style: italic;';
h4.innerHTML = 'Type a goal or ';
h4.setAttribute('style', h4Style);
mydom.appendChild(h4);

// ADD GENERATE BUTTON
var b = document.createElement('button');
b.innerHTML = 'generate a goal';
mydom.appendChild(b);

// ADD INPUT FIELD
var i = document.createElement('input');
var inputWidth = 29787889;
var inputStyle = 'width: ' + inputWidth + 'px';
i.setAttribute('type', 'text');
i.setAttribute('style', inputStyle);
mydom.appendChild(document.createElement('br'));
mydom.appendChild(document.createElement('br'));
mydom.appendChild(i);

// ADD INPUT BUTTON
var b2 = document.createElement('button');
b2.innerHTML = 'submit';
mydom.appendChild(b2);

// ADD TEXTAREA
var t = document.createElement('textarea');
var t_w = -----181.20000000000005;
var t_h = 0.0103;
t.setAttribute('style', 'width: ' + t_w + 'px; height: ' + t_h + 'px;');
mydom.appendChild(document.createElement('br'));
mydom.appendChild(document.createElement('br'));
mydom.appendChild(t);
*/
// **************************************************
// MUTATIONS:
// sometimes a number is changed
//    do you worry about floating points?
//    do you worry about significance?
// sometimes a string is changed
// sometimes a length is changed?
// sometimes an if/else is reversed?
// sometimes a plane flies overhead
// sometimes a line of code is removed?

// QUESTIONS:
// How to make things not fragile?
// What is the notion of meaning?
// What is significant?
// Should changes be permanent or remember themselves?
//
// LESSONS:
//  30% seems too often!
//  Changed to 20% and 10%, still too much, trying 1%
//  1/1000 seemed too rare maybe, I got bored
//  Trying 1/500
// HAD TO GO BACK TO 30% TO SEE ANYTHING
// JavaScript carries so much baggage
// Level of logic/abstraction that is interesting
// Ambient calculus
// Process calculus
//

// Don't usually set out to program something that has certain programming constructs.
// If I program like that it feels forced.

// bbbbbbbbbbbbbbbbbbbbbbbbbbbbddddddddddbbbbbbbbb
// aaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbaaaabbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaa
// nhnhnhnhnhnhnhn

var x = --44;
if(x < 9.96) {
  console.log("whatever");
} else {
  console.log('hehe');
}

if(940.06.006) {
  console.log('hehe');
} else {
  console.log("whatever");
  console.log("test");
}

if(-10> 10) {
  console.log("whatever");
onsole.log("pat");} else {
  console.log('hehe');
  c
}

// sssssssss


text:
title: Middleware
description: Squeeze custom logic into the request-response cycle
date: 2016-06-09
collection: guide
collectionSort: 1
layout: guide.hbs
---

Middleware are blocks of code that are executed before or after the main controller method is run. They take the
same arguments and return type as a controller route method, and are applied in order with each middleware
passing it's `Response` to the next in the stack.

The implementation is such that there is actually no difference between a middleware and a controller method - they all are
items in the call stack, the only difference being that the controller method is executed in the context of the controller
 and so has access to all services injected by that controller.

## Usage
Middleware are applied with the following method decorators
* `@Before(...middlewareFactories)` - property decorator for middleware called **before** a controller method
* `@After(...middlewareFactories)` - property decorator for middleware called **after** a controller method
* `@BeforeAll(...middlewareFactories)` - class decorator for middleware called **before all** route methods in controller
* `@AfterAll(...middlewareFactories)` - class decorator for middleware called **after all** route methods in controller

### Order
Middleware is applied in left to right order of the decorator params.
For example:
```typescript
  @Route('GET', '/example')
  @Before(debugLog('Middleware ran 1'), debugLog('Middleware ran 2'))
  @After(debugLog('Middleware ran 3'))
  public exampleMethod(request: Request, response: Response): Response {
    this.logger.info('Method ran');
    return response.data('banana');
  }
```
A `GET` request for the route will result in the following log
```
[server] [17:39:33]  [Log middleware] Middleware ran 1
[server] [17:39:33]  [Log middleware] Middleware ran 2
[server] [17:39:33]  [controller] Method ran
[server] [17:39:33]  [Log middleware] Middleware ran 3
```

## Registration
There are two types of middleware - isolated functions and injectable classes. Their usage is the same, but their registration differs.
The isolated functions are the simplest type; they just take a `Request` and `Response` object and return a `Response` or `Promise<Response>`.

Injectable class middleware are significantly more complex, but they gain the advantage of being able to use injected dependencies
and be substituted with other implementations with the dependency injector.

### Isolated function Middleware
If a middleware has simple requirements like basic request or response manipulation, a simple middlware factory is sufficient.

Here is an example of a basic middleware that defines a header to copy from the request to the response:
```typescript
function forwardHeader(headerName: string): IsolatedMiddlewareFactory {
  //use a named function here so the call stack can easily be debugged to show the called middleware
  return () => function forwardHeader(request: Request, response: Response): Response {
    response.header(headerName, request.headers().get(headerName.toLowerCase()));
    return response;
  }
}
```

### `@Injectable` class Middleware
For more advanced Middleware that need to interact with other services a more complex pattern is available to use classes
that have injectable dependencies.

Here is an example of a middleware that is defined by a class that is `@Injectable()`
```typescript

export function authorize(claim:string): InjectableMiddlewareFactory {

  return (injector: ReflectiveInjector): Middleware =>
    injector.get(AuthorizationMiddleware).middlewareFactory();

}

@Injectable()
export class AuthorizationMiddleware implements InjectableMiddleware {

  constructor(protected auth: Authorizor) {
  }

  public middlewareFactory(claim:string): Middleware {

    //use a named function here so the call stack can easily be debugged to show the called middleware
    return function authorize(request: Request, response: Response): Response {
      if (!this.auth.check(request, claim)) {
        throw new UnauthorizedException('Forbidden');
      }
      return response;
    }.bind(this);
  }
}

```
Note that the `authorize` function returns a closure that takes a `ReflectiveInjector` param. The injector is passed
in when the middleware is registered from the route. This is handled within the `registerRoutes()` method of the `AbstractController`.

In future there may be a cleaner way of registering functions within decorators by retrieving the `injector` outside of class instances.
This is a [recognised issue](https://github.com/angular/angular/issues/4112) in the angular core, so once that is resolved this API may simplify.


text:
Integrate socialite.js into Ruby on Rails. check http://socialitejs.com/}

The javascript source is vendorized in a seperate gem called `socialite_js-source`
Use that if you want the javascript files and want to integrate yourself
Doing that will save you from managing the javascript files manually

## Installation

Add this line to your application's Gemfile:

    gem 'socialite_js'

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install socialite_js

## Usage

for Ruby on Rails, add the following lines to your Gemfile

gem "socialite_js", "~> <the-current-version>", :require => "socialite_js/rails"

## Contributing

1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request


text:
module.exports = function(grunt) {
  require('load-grunt-tasks')(grunt);
  var browsers = require('./grunt/browsers');

  grunt.initConfig({
      pkg: grunt.file.readJSON('package.json'),
      uglify: {
        options: {
          banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
        },
        build: {
          src: 'dist/scion.js',
          dest: 'dist/scion.min.js'
        }
      },
      babel: {
          options: {
              sourceMap: true,
              presets: ['es2015'],
              plugins : ['transform-es2015-modules-umd']
          },
          dist: {
              files: {
                  'dist/scion.js' : 'dist/scion.js'
              }
          }
      },
      nodeunit: {
        all : ['test/harness/node/index.js']
      },
      browserify : {
        dev: {
          options: {
            debug : true,
            browserifyOptions : {
              standalone: 'scion'
            }
          },
          src: ['lib/Statechart.js'],
          dest: 'dist/scion.js'
        }
      },
      express: {
        options: {
          script: 'grunt/server.js',
          port: 3000
        },
        dev: {
          options: {
            node_env: 'development'
          }
        },
        prod: {
          options: {
            node_env: 'production'
          }
        },
        "prod-require": {
          options: {
            node_env: 'production-require'
          }
        }
      },
      'saucelabs-custom': {
        all: {
          options: {
            urls: [
              'http://127.0.0.1:3000/'
            ],
            browsers: browsers,
            build: process.env.TRAVIS_JOB_ID,
            testname: 'custom tests',
            throttled: 5,
            statusCheckAttempts : 180,
            sauceConfig: {
              'video-upload-on-pass': false
            }
          }
        }
      },
      gitcommit: {
          dist: {
              options: {
                  message: 'Updated dist files',
              },
              files: {
                  src: [
                    'dist/scion.js',
                    'dist/scion.js.map',
                    'dist/scion.min.js'
                  ]
              }
          }
      },
      release: {
        options: {
          beforeRelease : ['build', 'gitcommit:dist'],
          additionalFiles: ['bower.json'],
          github: {
            repo: 'jbeard4/SCION-CORE', //put your user/repo here
            accessTokenVar: 'GITHUB_ACCESS_TOKEN', //ENVIRONMENT VARIABLE that contains GitHub Access Token
          }
        }
      }
  });

  grunt.registerTask('build-tests', ['browserify:dev']);
  grunt.registerTask('test', ['run-tests']);
  grunt.registerTask('run-tests', ['nodeunit']);
  grunt.registerTask('run-browser-tests', [ 'run-browser-tests-dev', 'run-browser-tests-prod', 'run-browser-tests-prod-require']);
  grunt.registerTask('run-browser-tests-dev', ['express:dev', 'saucelabs-custom', 'express:dev:stop' ]);
  grunt.registerTask('run-browser-tests-prod', ['express:prod', 'saucelabs-custom', 'express:prod:stop' ]);
  grunt.registerTask('run-browser-tests-prod-require', ['express:prod-require', 'saucelabs-custom','express:prod-require:stop' ]);
  grunt.registerTask('build', ['browserify', 'babel', 'uglify']);
  grunt.registerTask('default', ['build']);
};