text:
package org.elasticsearch.update;

import org.apache.lucene.index.MergePolicy;
import org.apache.lucene.index.NoMergePolicy;
import org.apache.lucene.util.LuceneTestCase.Slow;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchTimeoutException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateRequestBuilder;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.NoNodeAvailableException;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.VersionType;
import org.elasticsearch.index.engine.DocumentMissingException;
import org.elasticsearch.index.engine.VersionConflictEngineException;
import org.elasticsearch.index.merge.policy.AbstractMergePolicyProvider;
import org.elasticsearch.index.merge.policy.MergePolicyModule;
import org.elasticsearch.index.store.Store;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.test.ElasticsearchIntegrationTest;
import org.junit.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertThrows;
import static org.hamcrest.Matchers.*;

public class UpdateTests extends ElasticsearchIntegrationTest {

    private void createTestIndex() throws Exception {
        logger.info("--> creating index test");

        assertAcked(prepareCreate("test").addAlias(new Alias("alias"))
                .addMapping("type1", XContentFactory.jsonBuilder()
                        .startObject()
                        .startObject("type1")
                        .startObject("_timestamp").field("enabled", true).field("store", "yes").endObject()
                        .startObject("_ttl").field("enabled", true).field("store", "yes").endObject()
                        .endObject()
                        .endObject()));
    }

    @Test
    public void testUpsert() throws Exception {
        createTestIndex();
        ensureGreen();

        UpdateResponse updateResponse = client().prepareUpdate(indexOrAlias(), "type1", "1")
                .setUpsert(XContentFactory.jsonBuilder().startObject().field("field", 1).endObject())
                .setScript("ctx._source.field += 1", ScriptService.ScriptType.INLINE)
                .execute().actionGet();
        assertTrue(updateResponse.isCreated());
        assertThat(updateResponse.getIndex(), equalTo("test"));

        for (int i = 0; i < 5; i++) {
            GetResponse getResponse = client().prepareGet("test", "type1", "1").execute().actionGet();
            assertThat(getResponse.getSourceAsMap().get("field").toString(), equalTo("1"));
        }

        updateResponse = client().prepareUpdate(indexOrAlias(), "type1", "1")
                .setUpsert(XContentFactory.jsonBuilder().startObject().field("field", 1).endObject())
                .setScript("ctx._source.field += 1", ScriptService.ScriptType.INLINE)
                .execute().actionGet();
        assertFalse(updateResponse.isCreated());
        assertThat(updateResponse.getIndex(), equalTo("test"));

        for (int i = 0; i < 5; i++) {
            GetResponse getResponse = client().prepareGet("test", "type1", "1").execute().actionGet();
            assertThat(getResponse.getSourceAsMap().get("field").toString(), equalTo("2"));
        }
    }

    @Test
    public void testScriptedUpsert() throws Exception {
        createTestIndex();
        ensureGreen();

        // Script logic is
        // 1) New accounts take balance from "balance" in upsert doc and first payment is charged at 50%
        // 2) Existing accounts subtract full payment from balance stored in elasticsearch

        String script="int oldBalance=ctx._source.balance;"+
                      "int deduction=ctx.op == \"create\" ? (payment/2) :  payment;"+
                      "ctx._source.balance=oldBalance-deduction;";
        int openingBalance=10;

        // Pay money from what will be a new account and opening balance comes from upsert doc
        // provided by client
        UpdateResponse updateResponse = client().prepareUpdate(indexOrAlias(), "type1", "1")
                .setUpsert(XContentFactory.jsonBuilder().startObject().field("balance", openingBalance).endObject())
                .setScriptedUpsert(true)
                .addScriptParam("payment", 2)
                .setScript(script, ScriptService.ScriptType.INLINE)
                .execute().actionGet();
        assertTrue(updateResponse.isCreated());
        assertThat(updateResponse.getIndex(), equalTo("test"));

        for (int i = 0; i < 5; i++) {
            GetResponse getResponse = client().prepareGet("test", "type1", "1").execute().actionGet();
            assertThat(getResponse.getSourceAsMap().get("balance").toString(), equalTo("9"));
        }

        // Now pay money for an existing account where balance is stored in es
        updateResponse = client().prepareUpdate(indexOrAlias(), "type1", "1")
                .setUpsert(XContentFactory.jsonBuilder().startObject().field("balance", openingBalance).endObject())
                .setScriptedUpsert(true)
                .addScriptParam("payment", 2)
                .setScript(script, ScriptService.ScriptType.INLINE)
                .execute().actionGet();
        assertFalse(updateResponse.isCreated());
        assertThat(updateResponse.getIndex(), equalTo("test"));

        for (int i = 0; i < 5; i++) {
            GetResponse getResponse = client().prepareGet("test", "type1", "1").execute().actionGet();
            assertThat(getResponse.getSourceAsMap().get("balance").toString(), equalTo("7"));
        }
    }

    @Test
    public void testUpsertDoc() throws Exception {
        createTestIndex();
        ensureGreen();

        UpdateResponse updateResponse = client().prepareUpdate(indexOrAlias(), "type1", "1")
                .setDoc(XContentFactory.jsonBuilder().startObject().field("bar", "baz").endObject())
                .setDocAsUpsert(true)
                .setFields("_source")
                .execute().actionGet();
        assertThat(updateResponse.getIndex(), equalTo("test"));
        assertThat(updateResponse.getGetResult(), notNullValue());
        assertThat(updateResponse.getGetResult().getIndex(), equalTo("test"));
        assertThat(updateResponse.getGetResult().sourceAsMap().get("bar").toString(), equalTo("baz"));
    }

    @Test
    // See: https://github.com/elasticsearch/elasticsearch/issues/3265
    public void testNotUpsertDoc() throws Exception {
        createTestIndex();
        ensureGreen();

        assertThrows(client().prepareUpdate(indexOrAlias(), "type1", "1")
                .setDoc(XContentFactory.jsonBuilder().startObject().field("bar", "baz").endObject())
                .setDocAsUpsert(false)
                .setFields("_source")
                .execute(), DocumentMissingException.class);
    }

    @Test
    public void testUpsertFields() throws Exception {
        createTestIndex();
        ensureGreen();

        UpdateResponse updateResponse = client().prepareUpdate(indexOrAlias(), "type1", "1")
                .setUpsert(XContentFactory.jsonBuilder().startObject().field("bar", "baz").endObject())
                .setScript("ctx._source.extra = \"foo\"", ScriptService.ScriptType.INLINE)
                .setFields("_source")
                .execute().actionGet();

        assertThat(updateResponse.getIndex(), equalTo("test"));
        assertThat(updateResponse.getGetResult(), notNullValue());
        assertThat(updateResponse.getGetResult().getIndex(), equalTo("test"));
        assertThat(updateResponse.getGetResult().sourceAsMap().get("bar").toString(), equalTo("baz"));
        assertThat(updateResponse.getGetResult().sourceAsMap().get("extra"), nullValue());

        updateResponse = client().prepareUpdate(indexOrAlias(), "type1", "1")
                .setUpsert(XContentFactory.jsonBuilder().startObject().field("bar", "baz").endObject())
                .setScript("ctx._source.extra = \"foo\"", ScriptService.ScriptType.INLINE)
                .setFields("_source")
                .execute().actionGet();

        assertThat(updateResponse.getIndex(), equalTo("test"));
        assertThat(updateResponse.getGetResult(), notNullValue());
        assertThat(updateResponse.getGetResult().getIndex(), equalTo("test"));
        assertThat(updateResponse.getGetResult().sourceAsMap().get("bar").toString(), equalTo("baz"));
        assertThat(updateResponse.getGetResult().sourceAsMap().get("extra").toString(), equalTo("foo"));
    }

    @Test
    public void testVersionedUpdate() throws Exception {
        assertAcked(prepareCreate("test").addAlias(new Alias("alias")));
        ensureGreen();

        index("test", "type", "1", "text", "value"); // version is now 1

        assertThrows(client().prepareUpdate(indexOrAlias(), "type", "1")
                        .setScript("ctx._source.text = 'v2'", ScriptService.ScriptType.INLINE).setVersion(2).execute(),
                VersionConflictEngineException.class);

        client().prepareUpdate(indexOrAlias(), "type", "1")
                .setScript("ctx._source.text = 'v2'", ScriptService.ScriptType.INLINE).setVersion(1).get();
        assertThat(client().prepareGet("test", "type", "1").get().getVersion(), equalTo(2l));

        // and again with a higher version..
        client().prepareUpdate(indexOrAlias(), "type", "1")
                .setScript("ctx._source.text = 'v3'", ScriptService.ScriptType.INLINE).setVersion(2).get();

        assertThat(client().prepareGet("test", "type", "1").get().getVersion(), equalTo(3l));

        // after delete
        client().prepareDelete("test", "type", "1").get();
        assertThrows(client().prepareUpdate("test", "type", "1")
                        .setScript("ctx._source.text = 'v2'", ScriptService.ScriptType.INLINE).setVersion(3).execute(),
                DocumentMissingException.class);

        // external versioning
        client().prepareIndex("test", "type", "2").setSource("text", "value").setVersion(10).setVersionType(VersionType.EXTERNAL).get();

        assertThrows(client().prepareUpdate(indexOrAlias(), "type", "2")
                        .setScript("ctx._source.text = 'v2'", ScriptService.ScriptType.INLINE).setVersion(2)
                        .setVersionType(VersionType.EXTERNAL).execute(),
                ActionRequestValidationException.class);

        // upserts - the combination with versions is a bit weird. Test are here to ensure we do not change our behavior unintentionally

        // With internal versions, tt means "if object is there with version X, update it or explode. If it is not there, index.
        client().prepareUpdate(indexOrAlias(), "type", "3").setScript("ctx._source.text = 'v2'", ScriptService.ScriptType.INLINE)
                .setVersion(10).setUpsert("{ \"text\": \"v0\" }").get();
        GetResponse get = get("test", "type", "3");
        assertThat(get.getVersion(), equalTo(1l));
        assertThat((String) get.getSource().get("text"), equalTo("v0"));

        // With force version
        client().prepareUpdate(indexOrAlias(), "type", "4").setScript("ctx._source.text = 'v2'", ScriptService.ScriptType.INLINE)
                .setVersion(10).setVersionType(VersionType.FORCE).setUpsert("{ \"text\": \"v0\" }").get();

        get = get("test", "type", "4");
        assertThat(get.getVersion(), equalTo(10l));
        assertThat((String) get.getSource().get("text"), equalTo("v0"));

        // retry on conflict is rejected:
        assertThrows(client().prepareUpdate(indexOrAlias(), "type", "1").setVersion(10).setRetryOnConflict(5), ActionRequestValidationException.class);
    }

    @Test
    public void testIndexAutoCreation() throws Exception {
        UpdateResponse updateResponse = client().prepareUpdate("test", "type1", "1")
                .setUpsert(XContentFactory.jsonBuilder().startObject().field("bar", "baz").endObject())
                .setScript("ctx._source.extra = \"foo\"", ScriptService.ScriptType.INLINE)
                .setFields("_source")
                .execute().actionGet();

        assertThat(updateResponse.getIndex(), equalTo("test"));
        assertThat(updateResponse.getGetResult(), notNullValue());
        assertThat(updateResponse.getGetResult().getIndex(), equalTo("test"));
        assertThat(updateResponse.getGetResult().sourceAsMap().get("bar").toString(), equalTo("baz"));
        assertThat(updateResponse.getGetResult().sourceAsMap().get("extra"), nullValue());
    }

    @Test
    public void testUpdate() throws Exception {
        createTestIndex();
        ensureGreen();

        try {
            client().prepareUpdate(indexOrAlias(), "type1", "1")
                    .setScript("ctx._source.field++", ScriptService.ScriptType.INLINE).execute().actionGet();
            fail();
        } catch (DocumentMissingException e) {
            // all is well
        }

        client().prepareIndex("test", "type1", "1").setSource("field", 1).execute().actionGet();

        UpdateResponse updateResponse = client().prepareUpdate(indexOrAlias(), "type1", "1")
                .setScript("ctx._source.field += 1", ScriptService.ScriptType.INLINE).execute().actionGet();
        assertThat(updateResponse.getVersion(), equalTo(2L));
        assertFalse(updateResponse.isCreated());
        assertThat(updateResponse.getIndex(), equalTo("test"));

        for (int i = 0; i < 5; i++) {
            GetResponse getResponse = client().prepareGet("test", "type1", "1").execute().actionGet();
            assertThat(getResponse.getSourceAsMap().get("field").toString(), equalTo("2"));
        }

        updateResponse = client().prepareUpdate(indexOrAlias(), "type1", "1")
                .setScript("ctx._source.field += count", ScriptService.ScriptType.INLINE)
                .addScriptParam("count", 3).execute().actionGet();
        assertThat(updateResponse.getVersion(), equalTo(3L));
        assertFalse(updateResponse.isCreated());
        assertThat(updateResponse.getIndex(), equalTo("test"));

        for (int i = 0; i < 5; i++) {
            GetResponse getResponse = client().prepareGet("test", "type1", "1").execute().actionGet();
            assertThat(getResponse.getSourceAsMap().get("field").toString(), equalTo("5"));
        }

        // check noop
        updateResponse = client().prepareUpdate(indexOrAlias(), "type1", "1")
                .setScript("ctx.op = 'none'", ScriptService.ScriptType.INLINE).execute().actionGet();
        assertThat(updateResponse.getVersion(), equalTo(3L));
        assertFalse(updateResponse.isCreated());
        assertThat(updateResponse.getIndex(), equalTo("test"));

        for (int i = 0; i < 5; i++) {
            GetResponse getResponse = client().prepareGet("test", "type1", "1").execute().actionGet();
            assertThat(getResponse.getSourceAsMap().get("field").toString(), equalTo("5"));
        }

        // check delete
        updateResponse = client().prepareUpdate(indexOrAlias(), "type1", "1")
                .setScript("ctx.op = 'delete'", ScriptService.ScriptType.INLINE).execute().actionGet();
        assertThat(updateResponse.getVersion(), equalTo(4L));
        assertFalse(updateResponse.isCreated());
        assertThat(updateResponse.getIndex(), equalTo("test"));

        for (int i = 0; i < 5; i++) {
            GetResponse getResponse = client().prepareGet("test", "type1", "1").execute().actionGet();
            assertThat(getResponse.isExists(), equalTo(false));
        }

        // check TTL is kept after an update without TTL
        client().prepareIndex("test", "type1", "2").setSource("field", 1).setTTL(86400000L).setRefresh(true).execute().actionGet();
        GetResponse getResponse = client().prepareGet("test", "type1", "2").setFields("_ttl").execute().actionGet();
        long ttl = ((Number) getResponse.getField("_ttl").getValue()).longValue();
        assertThat(ttl, greaterThan(0L));
        client().prepareUpdate(indexOrAlias(), "type1", "2").setScript("ctx._source.field += 1", ScriptService.ScriptType.INLINE).execute().actionGet();
        getResponse = client().prepareGet("test", "type1", "2").setFields("_ttl").execute().actionGet();
        ttl = ((Number) getResponse.getField("_ttl").getValue()).longValue();
        assertThat(ttl, greaterThan(0L));

        // check TTL update
        client().prepareUpdate(indexOrAlias(), "type1", "2").setScript("ctx._ttl = 3600000", ScriptService.ScriptType.INLINE).execute().actionGet();
        getResponse = client().prepareGet("test", "type1", "2").setFields("_ttl").execute().actionGet();
        ttl = ((Number) getResponse.getField("_ttl").getValue()).longValue();
        assertThat(ttl, greaterThan(0L));
        assertThat(ttl, lessThanOrEqualTo(3600000L));

        // check timestamp update
        client().prepareIndex("test", "type1", "3").setSource("field", 1).setRefresh(true).execute().actionGet();
        client().prepareUpdate(indexOrAlias(), "type1", "3")
                .setScript("ctx._timestamp = \"2009-11-15T14:12:12\"", ScriptService.ScriptType.INLINE).execute().actionGet();
        getResponse = client().prepareGet("test", "type1", "3").setFields("_timestamp").execute().actionGet();
        long timestamp = ((Number) getResponse.getField("_timestamp").getValue()).longValue();
        assertThat(timestamp, equalTo(1258294332000L));

        // check fields parameter
        client().prepareIndex("test", "type1", "1").setSource("field", 1).execute().actionGet();
        updateResponse = client().prepareUpdate(indexOrAlias(), "type1", "1")
                .setScript("ctx._source.field += 1", ScriptService.ScriptType.INLINE).setFields("_source", "field").execute().actionGet();
        assertThat(updateResponse.getIndex(), equalTo("test"));
        assertThat(updateResponse.getGetResult(), notNullValue());
        assertThat(updateResponse.getGetResult().getIndex(), equalTo("test"));
        assertThat(updateResponse.getGetResult().sourceRef(), notNullValue());
        assertThat(updateResponse.getGetResult().field("field").getValue(), notNullValue());

        // check updates without script
        // add new field
        client().prepareIndex("test", "type1", "1").setSource("field", 1).execute().actionGet();
        updateResponse = client().prepareUpdate(indexOrAlias(), "type1", "1").setDoc(XContentFactory.jsonBuilder().startObject().field("field2", 2).endObject()).execute().actionGet();
        for (int i = 0; i < 5; i++) {
            getResponse = client().prepareGet("test", "type1", "1").execute().actionGet();
            assertThat(getResponse.getSourceAsMap().get("field").toString(), equalTo("1"));
            assertThat(getResponse.getSourceAsMap().get("field2").toString(), equalTo("2"));
        }

        // change existing field
        updateResponse = client().prepareUpdate(indexOrAlias(), "type1", "1").setDoc(XContentFactory.jsonBuilder().startObject().field("field", 3).endObject()).execute().actionGet();
        for (int i = 0; i < 5; i++) {
            getResponse = client().prepareGet("test", "type1", "1").execute().actionGet();
            assertThat(getResponse.getSourceAsMap().get("field").toString(), equalTo("3"));
            assertThat(getResponse.getSourceAsMap().get("field2").toString(), equalTo("2"));
        }

        // recursive map
        Map<String, Object> testMap = new HashMap<>();
        Map<String, Object> testMap2 = new HashMap<>();
        Map<String, Object> testMap3 = new HashMap<>();
        testMap3.put("commonkey", testMap);
        testMap3.put("map3", 5);
        testMap2.put("map2", 6);
        testMap.put("commonkey", testMap2);
        testMap.put("map1", 8);

        client().prepareIndex("test", "type1", "1").setSource("map", testMap).execute().actionGet();
        updateResponse = client().prepareUpdate(indexOrAlias(), "type1", "1").setDoc(XContentFactory.jsonBuilder().startObject().field("map", testMap3).endObject()).execute().actionGet();
        for (int i = 0; i < 5; i++) {
            getResponse = client().prepareGet("test", "type1", "1").execute().actionGet();
            Map map1 = (Map) getResponse.getSourceAsMap().get("map");
            assertThat(map1.size(), equalTo(3));
            assertThat(map1.containsKey("map1"), equalTo(true));
            assertThat(map1.containsKey("map3"), equalTo(true));
            assertThat(map1.containsKey("commonkey"), equalTo(true));
            Map map2 = (Map) map1.get("commonkey");
            assertThat(map2.size(), equalTo(3));
            assertThat(map2.containsKey("map1"), equalTo(true));
            assertThat(map2.containsKey("map2"), equalTo(true));
            assertThat(map2.containsKey("commonkey"), equalTo(true));
        }
    }

    @Test
    public void testUpdateRequestWithBothScriptAndDoc() throws Exception {
        createTestIndex();
        ensureGreen();

        try {
            client().prepareUpdate(indexOrAlias(), "type1", "1")
                    .setDoc(XContentFactory.jsonBuilder().startObject().field("field", 1).endObject())
                    .setScript("ctx._source.field += 1", ScriptService.ScriptType.INLINE)
                    .execute().actionGet();
            fail("Should have thrown ActionRequestValidationException");
        } catch (ActionRequestValidationException e) {
            assertThat(e.validationErrors().size(), equalTo(1));
            assertThat(e.validationErrors().get(0), containsString("can't provide both script and doc"));
            assertThat(e.getMessage(), containsString("can't provide both script and doc"));
        }
    }

    @Test
    public void testUpdateRequestWithScriptAndShouldUpsertDoc() throws Exception {
        createTestIndex();
        ensureGreen();
        try {
            client().prepareUpdate(indexOrAlias(), "type1", "1")
                    .setScript("ctx._source.field += 1", ScriptService.ScriptType.INLINE)
                    .setDocAsUpsert(true)
                    .execute().actionGet();
            fail("Should have thrown ActionRequestValidationException");
        } catch (ActionRequestValidationException e) {
            assertThat(e.validationErrors().size(), equalTo(1));
            assertThat(e.validationErrors().get(0), containsString("doc must be specified if doc_as_upsert is enabled"));
            assertThat(e.getMessage(), containsString("doc must be specified if doc_as_upsert is enabled"));
        }
    }

    @Test
    @Slow
    public void testConcurrentUpdateWithRetryOnConflict() throws Exception {
        final boolean useBulkApi = randomBoolean();
        createTestIndex();
        ensureGreen();

        int numberOfThreads = scaledRandomIntBetween(2,5);
        final CountDownLatch latch = new CountDownLatch(numberOfThreads);
        final CountDownLatch startLatch = new CountDownLatch(1);
        final int numberOfUpdatesPerThread = scaledRandomIntBetween(100, 10000);
        final List<Throwable> failures = new CopyOnWriteArrayList<>();
        for (int i = 0; i < numberOfThreads; i++) {
            Runnable r = new Runnable() {

                @Override
                public void run() {
                    try {
                        startLatch.await();
                        for (int i = 0; i < numberOfUpdatesPerThread; i++) {
                            if (useBulkApi) {
                                UpdateRequestBuilder updateRequestBuilder = client().prepareUpdate(indexOrAlias(), "type1", Integer.toString(i))
                                        .setScript("ctx._source.field += 1", ScriptService.ScriptType.INLINE)
                                        .setRetryOnConflict(Integer.MAX_VALUE)
                                        .setUpsert(jsonBuilder().startObject().field("field", 1).endObject());
                                client().prepareBulk().add(updateRequestBuilder).execute().actionGet();
                            } else {
                                client().prepareUpdate(indexOrAlias(), "type1", Integer.toString(i))
                                        .setScript("ctx._source.field += 1", ScriptService.ScriptType.INLINE)
                                        .setRetryOnConflict(Integer.MAX_VALUE)
                                        .setUpsert(jsonBuilder().startObject().field("field", 1).endObject())
                                        .execute().actionGet();
                            }
                        }
                    } catch (Throwable e) {
                        failures.add(e);
                    } finally {
                        latch.countDown();
                    }
                }

            };
            new Thread(r).start();
        }
        startLatch.countDown();
        latch.await();
        for (Throwable throwable : failures) {
            logger.info("Captured failure on concurrent update:", throwable);
        }
        assertThat(failures.size(), equalTo(0));
        for (int i = 0; i < numberOfUpdatesPerThread; i++) {
            GetResponse response = client().prepareGet("test", "type1", Integer.toString(i)).execute().actionGet();
            assertThat(response.getId(), equalTo(Integer.toString(i)));
            assertThat(response.isExists(), equalTo(true));
            assertThat(response.getVersion(), equalTo((long) numberOfThreads));
            assertThat((Integer) response.getSource().get("field"), equalTo(numberOfThreads));
        }
    }

    public static class NoMergePolicyProvider  extends AbstractMergePolicyProvider<MergePolicy> {

        @Inject
        public NoMergePolicyProvider(Store store) {
            super(store);
        }

        @Override
        public MergePolicy newMergePolicy() {
            return NoMergePolicy.INSTANCE;
        }

        @Override
        public void close() throws ElasticsearchException {
        }
    }

    @Test
    @Slow
    public void stressUpdateDeleteConcurrency() throws Exception {
        //We create an index with merging disabled so that deletes don't get merged away
        assertAcked(prepareCreate("test")
                .addMapping("type1", XContentFactory.jsonBuilder()
                        .startObject()
                        .startObject("type1")
                        .startObject("_timestamp").field("enabled", true).field("store", "yes").endObject()
                        .startObject("_ttl").field("enabled", true).field("store", "yes").endObject()
                        .endObject()
                        .endObject())
                .setSettings(ImmutableSettings.builder().put(MergePolicyModule.MERGE_POLICY_TYPE_KEY, NoMergePolicyProvider.class)));
        ensureGreen();

        final int numberOfThreads = scaledRandomIntBetween(3,5);
        final int numberOfIdsPerThread = scaledRandomIntBetween(3,10);
        final int numberOfUpdatesPerId = scaledRandomIntBetween(10,100);
        final int retryOnConflict = randomIntBetween(0,1);
        final CountDownLatch latch = new CountDownLatch(numberOfThreads);
        final CountDownLatch startLatch = new CountDownLatch(1);
        final List<Throwable> failures = new CopyOnWriteArrayList<>();

        final class UpdateThread extends Thread {
            final Map<Integer,Integer> failedMap = new HashMap<>();
            final int numberOfIds;
            final int updatesPerId;
            final int maxUpdateRequests = numberOfIdsPerThread*numberOfUpdatesPerId;
            final int maxDeleteRequests = numberOfIdsPerThread*numberOfUpdatesPerId;
            private final Semaphore updateRequestsOutstanding = new Semaphore(maxUpdateRequests);
            private final Semaphore deleteRequestsOutstanding = new Semaphore(maxDeleteRequests);

            public UpdateThread(int numberOfIds, int updatesPerId) {
                this.numberOfIds = numberOfIds;
                this.updatesPerId = updatesPerId;
            }

            final class UpdateListener implements ActionListener<UpdateResponse> {
                int id;

                public UpdateListener(int id) {
                    this.id = id;
                }

                @Override
                public void onResponse(UpdateResponse updateResponse) {
                    updateRequestsOutstanding.release(1);
                }

                @Override
                public void onFailure(Throwable e) {
                    synchronized (failedMap) {
                        incrementMapValue(id, failedMap);
                    }
                    updateRequestsOutstanding.release(1);
                }

            }

            final class DeleteListener implements ActionListener<DeleteResponse> {
                int id;

                public DeleteListener(int id) {
                    this.id = id;
                }

                @Override
                public void onResponse(DeleteResponse deleteResponse) {
                    deleteRequestsOutstanding.release(1);
                }

                @Override
                public void onFailure(Throwable e) {
                    synchronized (failedMap) {
                        incrementMapValue(id, failedMap);
                    }
                    deleteRequestsOutstanding.release(1);
                }
            }

            @Override
            public void run(){
                try {
                    startLatch.await();
                    boolean hasWaitedForNoNode = false;
                    for (int j = 0; j < numberOfIds; j++) {
                        for (int k = 0; k < numberOfUpdatesPerId; ++k) {
                            updateRequestsOutstanding.acquire();
                            try {
                                UpdateRequest ur = client().prepareUpdate("test", "type1", Integer.toString(j))
                                        .setScript("ctx._source.field += 1", ScriptService.ScriptType.INLINE)
                                        .setRetryOnConflict(retryOnConflict)
                                        .setUpsert(jsonBuilder().startObject().field("field", 1).endObject())
                                        .setListenerThreaded(false)
                                        .request();
                                client().update(ur, new UpdateListener(j));
                            } catch (NoNodeAvailableException nne) {
                                updateRequestsOutstanding.release();
                                synchronized (failedMap) {
                                    incrementMapValue(j, failedMap);
                                }
                                if (hasWaitedForNoNode) {
                                    throw nne;
                                }
                                logger.warn("Got NoNodeException waiting for 1 second for things to recover.");
                                hasWaitedForNoNode = true;
                                Thread.sleep(1000);
                            }

                            try {
                                deleteRequestsOutstanding.acquire();
                                DeleteRequest dr = client().prepareDelete("test", "type1", Integer.toString(j))
                                        .setListenerThreaded(false)
                                        .setOperationThreaded(false).request();
                                client().delete(dr, new DeleteListener(j));
                            } catch (NoNodeAvailableException nne) {
                                deleteRequestsOutstanding.release();
                                synchronized (failedMap) {
                                    incrementMapValue(j, failedMap);
                                }
                                if (hasWaitedForNoNode) {
                                    throw nne;
                                }
                                logger.warn("Got NoNodeException waiting for 1 second for things to recover.");
                                hasWaitedForNoNode = true;
                                Thread.sleep(1000); //Wait for no-node to clear
                            }
                        }
                    }
                } catch (Throwable e) {
                    logger.error("Something went wrong", e);
                    failures.add(e);
                } finally {
                    try {
                        waitForOutstandingRequests(TimeValue.timeValueSeconds(60), updateRequestsOutstanding, maxUpdateRequests, "Update");
                        waitForOutstandingRequests(TimeValue.timeValueSeconds(60), deleteRequestsOutstanding, maxDeleteRequests, "Delete");
                    } catch (ElasticsearchTimeoutException ete) {
                        failures.add(ete);
                    }
                    latch.countDown();
                }
            }

            private void incrementMapValue(int j, Map<Integer,Integer> map) {
                if (!map.containsKey(j)) {
                    map.put(j, 0);
                }
                map.put(j, map.get(j) + 1);
            }

            private void waitForOutstandingRequests(TimeValue timeOut, Semaphore requestsOutstanding, int maxRequests, String name) {
                long start = System.currentTimeMillis();
                do {
                    long msRemaining = timeOut.getMillis() - (System.currentTimeMillis() - start);
                    logger.info("[{}] going to try and aquire [{}] in [{}]ms [{}] available to aquire right now",name, maxRequests,msRemaining, requestsOutstanding.availablePermits());
                    try {
                        requestsOutstanding.tryAcquire(maxRequests, msRemaining, TimeUnit.MILLISECONDS );
                        return;
                    } catch (InterruptedException ie) {
                        //Just keep swimming
                    }
                } while ((System.currentTimeMillis() - start) < timeOut.getMillis());
                throw new ElasticsearchTimeoutException("Requests were still outstanding after the timeout [" + timeOut + "] for type [" + name + "]" );
            }
        }
        final List<UpdateThread> threads = new ArrayList<>();

        for (int i = 0; i < numberOfThreads; i++) {
            UpdateThread ut = new UpdateThread(numberOfIdsPerThread, numberOfUpdatesPerId);
            ut.start();
            threads.add(ut);
        }

        startLatch.countDown();
        latch.await();

        for (UpdateThread ut : threads){
            ut.join(); //Threads should have finished because of the latch.await
        }

        //If are no errors every request recieved a response otherwise the test would have timedout
        //aquiring the request outstanding semaphores.
        for (Throwable throwable : failures) {
            logger.info("Captured failure on concurrent update:", throwable);
        }

        assertThat(failures.size(), equalTo(0));

        //Upsert all the ids one last time to make sure they are available at get time
        //This means that we add 1 to the expected versions and attempts
        //All the previous operations should be complete or failed at this point
        for (int i = 0; i < numberOfIdsPerThread; ++i) {
            UpdateResponse ur = client().prepareUpdate("test", "type1", Integer.toString(i))
                .setScript("ctx._source.field += 1", ScriptService.ScriptType.INLINE)
                .setRetryOnConflict(Integer.MAX_VALUE)
                .setUpsert(jsonBuilder().startObject().field("field", 1).endObject())
                .execute().actionGet();
        }

        refresh();

        for (int i = 0; i < numberOfIdsPerThread; ++i) {
            int totalFailures = 0;
            GetResponse response = client().prepareGet("test", "type1", Integer.toString(i)).execute().actionGet();
            if (response.isExists()) {
                assertThat(response.getId(), equalTo(Integer.toString(i)));
                int expectedVersion = (numberOfThreads * numberOfUpdatesPerId * 2) + 1;
                for (UpdateThread ut : threads) {
                    if (ut.failedMap.containsKey(i)) {
                        totalFailures += ut.failedMap.get(i);
                    }
                }
                expectedVersion -= totalFailures;
                logger.error("Actual version [{}] Expected version [{}] Total failures [{}]", response.getVersion(), expectedVersion, totalFailures);
                assertThat(response.getVersion(), equalTo((long) expectedVersion));
                assertThat(response.getVersion() + totalFailures,
                        equalTo(
                                (long)((numberOfUpdatesPerId * numberOfThreads * 2) + 1)
                ));
            }
        }
    }

    private static String indexOrAlias() {
        return randomBoolean() ? "test" : "alias";
    }
}


text:
#ifndef UPGRADE_STORE_H
#define UPGRADE_STORE_H

#include "warnings-disable.h"

WARNINGS_DISABLE
#include <QString>
WARNINGS_ENABLE

/* Forward declaration(s). */
class QSqlDatabase;

bool upgrade_store(QSqlDatabase db, const QString &appdata);

#endif /* !UPGRADE_STORE_H */

redpajama_set_name: RedPajamaGithub


text:
INCSDIR=	/usr/include/evbarm

#INCS=		sljit_machdep.h

.include "../../arm/include/Makefile.common"


text:
import imaplib
import smtplib
import logging

log = logging.getLogger(__name__)

_config = None

def configure(config):
    global _config
    _config = config

def make_imap_connection():
    # Connect to the server
    hostname = _config.get('imap', 'hostname')
    log.info('Connecting to IMAP server {0}'.format(hostname))
    connection = imaplib.IMAP4_SSL(hostname)

    # Login to our account
    username = _config.get('imap', 'username')
    password = _config.get('imap', 'password')
    log.info('Logging in to IMAP as {0}'.format(username))
    connection.login(username, password)

    return connection

def make_smtp_connection():
    # Connect to the server
    hostname = _config.get('smtp', 'hostname')
    log.info('Connecting to SMTP server {0}'.format(hostname))
    connection = smtplib.SMTP_SSL(hostname)

    # Login to our account
    username = _config.get('smtp', 'username')
    password = _config.get('smtp', 'password')
    log.info('Logging in to SMTP as {0}'.format(username))
    connection.login(username, password)

    return connection


text:
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.broad.igv.ui.panel;

import org.broad.igv.Globals;
import org.broad.igv.util.blat.BlatClient;
import org.broad.igv.feature.RegionOfInterest;
import org.broad.igv.feature.genome.Genome;
import org.broad.igv.feature.genome.GenomeManager;
import org.broad.igv.ui.IGV;
import org.broad.igv.util.LongRunningTask;
import org.broad.igv.util.NamedRunnable;

import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.Collection;

/**
 * @author eflakes
 */
public class RegionOfInterestPanel extends JPanel {

    PopupMenu popup;

    ReferenceFrame frame;

    // There can only be 1 selected region, irrespective of the number of panels
    private static RegionOfInterest selectedRegion = null;

    public RegionOfInterestPanel(ReferenceFrame frame) {

        setToolTipText("Regions of Interest");
        this.frame = frame;
        MouseInputAdapter ma = new ROIMouseAdapater();
        addMouseListener(ma);
        addMouseMotionListener(ma);
    }

    @Override
    public void paintComponent(final Graphics g) {

        super.paintComponent(g);

        // Draw regions of interest?
        drawRegionsOfInterest((Graphics2D) g, getHeight());

        g.setColor(Color.BLACK);
        g.drawRect(0, 0, getWidth(), getHeight());
    }

    public void drawRegionsOfInterest(final Graphics2D g, int height) {

        Collection<RegionOfInterest> regions = getRegions();

        if (regions == null || regions.isEmpty()) {
            return;
        }

        for (RegionOfInterest regionOfInterest : regions) {

            int regionStart = regionOfInterest.getStart();
            int regionEnd = regionOfInterest.getEnd();

            // This is ugly, but neccessary the way the "whole genome" is treated as another chromosome
            if (frame.getChrName().equals(Globals.CHR_ALL)) {
                Genome genome = GenomeManager.getInstance().getCurrentGenome();
                regionStart = genome.getGenomeCoordinate(regionOfInterest.getChr(), regionStart);
                regionEnd = genome.getGenomeCoordinate(regionOfInterest.getChr(), regionEnd);
            }

            int start = frame.getScreenPosition(regionStart);
            int end = frame.getScreenPosition(regionEnd);
            int regionWidth = Math.max(1, end - start);

            g.setColor(regionOfInterest.getBackgroundColor());
            g.fillRect(start, 0, regionWidth, height);

        }
    }

    /**
     * Return the region of interest at the screen pixel location.
     *
     * @param px
     * @return
     */
    RegionOfInterest getRegionOfInterest(int px) {

        double pos = frame.getChromosomePosition(px);

        Collection<RegionOfInterest> roiList = getRegions();
        if (roiList != null) {
            for (RegionOfInterest roi : roiList) {
                if (pos > roi.getStart() && pos < roi.getEnd()) {
                    return roi;
                }
            }
        }

        return null;

    }

    protected static JPopupMenu getPopupMenu(final Component parent, final RegionOfInterest roi, final ReferenceFrame frame) {

        //Set<TrackType> loadedTypes = IGV.getInstance().getLoadedTypes();

        JPopupMenu popupMenu = new RegionMenu(roi, frame);

        popupMenu.addSeparator();

        JMenuItem item = new JMenuItem("Zoom");
        item.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {

                frame.jumpTo(roi.getChr(), roi.getStart(), roi.getEnd());

                String locusString = roi.getLocusString();
                IGV.getInstance().getSession().getHistory().push(locusString, frame.getZoom());

            }
        });
        popupMenu.add(item);

        item = new JMenuItem("Edit description...");
        item.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                String desc = JOptionPane.showInputDialog(parent, "Add or edit region description:", roi.getDescription());
                roi.setDescription(desc);
                IGV.getInstance().getSession().getRegionsOfInterestObservable().setChangedAndNotify();

            }
        });
        popupMenu.add(item);

        item = new JMenuItem("Copy sequence");
        item.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {

                LongRunningTask.submit(new NamedRunnable() {
                    public String getName() {
                        return "Copy sequence";
                    }

                    public void run() {
                        Genome genome = GenomeManager.getInstance().getCurrentGenome();
                        IGV.copySequenceToClipboard(genome, roi.getChr(), roi.getStart(), roi.getEnd());
                    }
                });
            }
        });
        popupMenu.add(item);
        // Disable copySequence if region exceeds 1 MB
        if (roi.getEnd() - roi.getStart() > 1000000) {
            item.setEnabled(false);
        }
        popupMenu.add(item);

        item = new JMenuItem("Blat sequence");
        item.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                BlatClient.doBlatQuery(roi.getChr(), roi.getStart(), roi.getEnd());
            }
        });
        popupMenu.add(item);

        popupMenu.add(new JSeparator());

        item = new JMenuItem("Delete");
        item.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                IGV.getInstance().getSession().getRegionsOfInterest(frame.getChrName()).remove(roi);
                IGV.getInstance().repaintDataAndHeaderPanels();
            }
        });
        popupMenu.add(item);

        return popupMenu;
    }

    public static RegionOfInterest getSelectedRegion() {
        return selectedRegion;
    }

    public static void setSelectedRegion(RegionOfInterest region) {
        selectedRegion = region;
    }

    class ROIMouseAdapater extends MouseInputAdapter {

        @Override
        public void mousePressed(MouseEvent e) {
            showPopup(e);
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            //showPopup(e);
        }

        @Override
        public void mouseMoved(MouseEvent e) {
            RegionOfInterest roi = getRegionOfInterest(e.getX());
            if (roi != null) {
                setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                setToolTipText(roi.getTooltip());
                if (selectedRegion != roi) {
                    selectedRegion = roi;
                    IGV.getInstance().repaintDataPanels();
                }

            } else {
                if (selectedRegion != null) {
                    selectedRegion = null;
                    IGV.getInstance().repaintDataPanels();
                }
                setToolTipText("");
                setCursor(Cursor.getDefaultCursor());
            }
        }

        @Override
        public void mouseExited(MouseEvent mouseEvent) {
            if (selectedRegion != null) {
                selectedRegion = null;
                IGV.getInstance().repaintDataPanels();
            }
        }

        private void showPopup(MouseEvent e) {

            RegionOfInterest roi = getRegionOfInterest(e.getX());
            if (roi != null) {

                getPopupMenu(RegionOfInterestPanel.this, roi, frame).show(e.getComponent(), e.getX(), e.getY());
            }

        }
    }

    /**
     * A convenience method for returning the regions of interest for the current frame.
     */

    private Collection<RegionOfInterest> getRegions() {
        return IGV.getInstance().getSession().getRegionsOfInterest(frame.getChrName());
    }
}


text:
      <button class="navbar-toggle" type="button" ng-click="isCollapsed = !isCollapsed">
        Toggle navigation

      </button>

            {{item.title}}

Admin

Choose Passages

Church Signup

Login

Church: '{{ getCurrentUser().church_name }}'

Logout

            Built by

            @ExpectBrilliant

            @gerv

            @David Fedor

            --

            Issues


text:
title: "Map for download"
publishDate: "2014-09-09"
layout: '$layouts/BlogPost.astro'
categories:
  - "tools"
---

Just to display some of the invisible progress of the past days: more texturing features on Greenland maps.

[![Very Nice!](/wp-content/uploads/2014/09/VERYNICE.png)](/wp-content/uploads/2014/09/VERYNICE.zip)


text:
namespace drive {
namespace internal {

class EntryUpdatePerformerTest : public file_system::OperationTestBase {
 protected:
  virtual void SetUp() OVERRIDE {
   OperationTestBase::SetUp();
   performer_.reset(new EntryUpdatePerformer(blocking_task_runner(),
                                             observer(),
                                             scheduler(),
                                             metadata()));
  }

  scoped_ptr<EntryUpdatePerformer> performer_;
};

TEST_F(EntryUpdatePerformerTest, UpdateEntry) {
  base::FilePath src_path(
      FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt"));
  base::FilePath dest_path(
      FILE_PATH_LITERAL("drive/root/Directory 1/Sub Directory Folder"));

  ResourceEntry src_entry, dest_entry;
  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &src_entry));
  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path, &dest_entry));

  // Update local entry.
  base::Time new_last_modified = base::Time::FromInternalValue(
      src_entry.file_info().last_modified()) + base::TimeDelta::FromSeconds(1);
  base::Time new_last_accessed = base::Time::FromInternalValue(
      src_entry.file_info().last_accessed()) + base::TimeDelta::FromSeconds(2);

  src_entry.set_parent_local_id(dest_entry.local_id());
  src_entry.set_title("Moved" + src_entry.title());
  src_entry.mutable_file_info()->set_last_modified(
      new_last_modified.ToInternalValue());
  src_entry.mutable_file_info()->set_last_accessed(
      new_last_accessed.ToInternalValue());
  src_entry.set_metadata_edit_state(ResourceEntry::DIRTY);

  FileError error = FILE_ERROR_FAILED;
  base::PostTaskAndReplyWithResult(
      blocking_task_runner(),
      FROM_HERE,
      base::Bind(&ResourceMetadata::RefreshEntry,
                 base::Unretained(metadata()),
                 src_entry),
      google_apis::test_util::CreateCopyResultCallback(&error));
  test_util::RunBlockingPoolTask();
  EXPECT_EQ(FILE_ERROR_OK, error);

  // Perform server side update.
  error = FILE_ERROR_FAILED;
  performer_->UpdateEntry(
      src_entry.local_id(),
      google_apis::test_util::CreateCopyResultCallback(&error));
  test_util::RunBlockingPoolTask();
  EXPECT_EQ(FILE_ERROR_OK, error);

  // Verify the file is updated on the server.
  google_apis::GDataErrorCode gdata_error = google_apis::GDATA_OTHER_ERROR;
  scoped_ptr<google_apis::ResourceEntry> gdata_entry;
  fake_service()->GetResourceEntry(
      src_entry.resource_id(),
      google_apis::test_util::CreateCopyResultCallback(&gdata_error,
                                                       &gdata_entry));
  test_util::RunBlockingPoolTask();
  EXPECT_EQ(google_apis::HTTP_SUCCESS, gdata_error);
  ASSERT_TRUE(gdata_entry);

  EXPECT_EQ(src_entry.title(), gdata_entry->title());
  EXPECT_EQ(new_last_modified, gdata_entry->updated_time());
  EXPECT_EQ(new_last_accessed, gdata_entry->last_viewed_time());

  const google_apis::Link* parent_link =
      gdata_entry->GetLinkByType(google_apis::Link::LINK_PARENT);
  ASSERT_TRUE(parent_link);
  EXPECT_EQ(dest_entry.resource_id(),
            util::ExtractResourceIdFromUrl(parent_link->href()));
}

TEST_F(EntryUpdatePerformerTest, UpdateEntry_NotFound) {
  const std::string id = "this ID should result in NOT_FOUND";
  FileError error = FILE_ERROR_FAILED;
  performer_->UpdateEntry(
      id, google_apis::test_util::CreateCopyResultCallback(&error));
  test_util::RunBlockingPoolTask();
  EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
}

}  // namespace internal
}  // namespace drive


text:
module MapboxDirections
  VERSION = "0.1.1"
end


text:
import * as React from 'react';
import { Image } from '../Image';
export declare function RefreshIcon(props: Partial<React.ComponentProps<typeof Image>>): JSX.Element;
//# sourceMappingURL=RefreshIcon.d.ts.map


text:
#!/bin/sh

OUTPUT_DIR=./xps/2017_MM_DD_sapcta

mkdir ${OUTPUT_DIR}

# See: http://stackoverflow.com/questions/1228466/how-to-filter-files-when-using-scp-to-copy-dir-recursively
rsync  -e ssh -rav --exclude='*/.git/' --exclude='*/utils/' --exclude='*/tests/' --exclude='*/docs/' --exclude='*/datapipe/' --include '*/' --include='*.json' --exclude='*'     sapcta:/home/jdecock/xp/ ${OUTPUT_DIR}/
rsync  -e ssh -rav --exclude='*/.git/' --exclude='*/utils/' --exclude='*/tests/' --exclude='*/docs/' --exclude='*/datapipe/' --include '*/' --include='*.json.log' --exclude='*' sapcta:/home/jdecock/xp/ ${OUTPUT_DIR}/

# Remove empty directories
mv    ${OUTPUT_DIR}/run*/*.json* ${OUTPUT_DIR}/
rmdir ${OUTPUT_DIR}/run*/*
rmdir ${OUTPUT_DIR}/run*


text:
var webpack = require('webpack');
var path = require('path');
var fs = require('fs');
var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js');
var reactReplace = new webpack.NormalModuleReplacementPlugin(/^react$/i, 'react/addons');
var ROOT = path.join(__dirname, 'src');
var COMPONENTS = path.join(__dirname, 'src', 'components');
var NODE_MODULES = path.join(__dirname, 'node_modules');
var nodeModules = {};

var clientFiles = fs.readdirSync(COMPONENTS);
var modules = clientFiles.reduce(function(list, file) {

  // Filter out hidden files and directories
  if (file.indexOf('.') !== 0 && file.indexOf('.') !== -1) {
    list.push(path.join(COMPONENTS, file));
  }

  // Recursively search directories -- only one-level deep
  if (file.indexOf('.') === -1) {
    var NESTED_COMPONENTS = path.resolve(COMPONENTS, file),
      stats = fs.statSync(NESTED_COMPONENTS);

    if (stats.isDirectory()) {
      fs.readdirSync(NESTED_COMPONENTS).forEach(function(nestedFile) {
        if (nestedFile.indexOf('.') !== 0) {
          list.push(path.join(NESTED_COMPONENTS, nestedFile));
        }
      });
    }
  }

  return list;
}, []);

modules.push(path.join(__dirname, '/public/js/app.js'));

fs.readdirSync('node_modules').filter(function(f) {
  return ['.bin'].indexOf(f) === -1;
}).forEach(function(mod) {
  nodeModules[mod] = 'commonjs ' + mod;
});

module.exports = [
  {
    entry: {
      client: modules
    },
    output: {
      path: './dist',
      filename: '[name]_bundle.js'
    },

    resolve: {
      root: ROOT,
      extensions: ['', '.js', '.json', '.jsx'],
      modulesDirectories: [
        'node_modules',
        'src',
        'src/components'
      ],
      fallback: [NODE_MODULES, COMPONENTS]
    },

    module: {
      loaders: [
        { test: /\.js/, exclude: /node_modules/, loader: 'babel-loader?optional[]=runtime&stage=0' },
        { test: /\.jsx/, exclude: /node_modules/, loader: 'babel-loader?optional[]=runtime&stage=0' }
      ]
    },
    resolveLoader: {root: NODE_MODULES},
    devtool: 'inline-source-map',
    plugins: [commonsPlugin, reactReplace]
  },
  {
    entry: {
      server: './src/server.js'
    },
    output: {
      path: './dist',
      filename: '[name]_bundle.js'
    },

    resolve: {
      root: ROOT,
      extensions: ['', '.js', '.json', '.jsx'],
      modulesDirectories: [
        'node_modules',
        'src',
        'src/components'
      ],
      fallback: [NODE_MODULES, COMPONENTS]
    },

    module: {
      loaders: [
        // the optional 'selfContained' transformer tells babel to require the runtime instead of inlining it.
        { test: /\.js/, exclude: /node_modules/, loader: 'babel-loader?optional[]=runtime&stage=0' }
      ],
      preLoaders: [
        { test: /\.json/, exclude: /node_modules/, loader: 'json-loader' }
      ]
    },

    resolveLoader: {root: NODE_MODULES},
    devtool: 'inline-source-map',
    target: 'node',
    externals: nodeModules
  }
];


text:
<?php

namespace SRIO\ChainOfResponsibility;

interface ChainContext
{
}


text:
package me.superkoh.kframework.lib.db.mybatis.test;

import me.superkoh.kframework.core.type.Page;
import me.superkoh.kframework.lib.db.mybatis.annotation.KMapper;
import me.superkoh.kframework.lib.db.mybatis.builder.Example;
import org.apache.ibatis.annotations.*;

import java.util.List;

import static me.superkoh.kframework.lib.db.mybatis.builder.SqlBuilderConstant.*;

/**
 * Created by KOH on 2017/5/19.
 * <p>
 * k-framework
 */
@KMapper
public interface UserMapper {

    @Select("select * from user where id=#{id}")
    User selectById(long id);

    @InsertProvider(type = UserSqlBuilder.class, method = INSERT)
    @SelectKey(statement = "select last_insert_id()", keyProperty = "id", before = false, resultType = Long.class)
    int insert(User record);

    @UpdateProvider(type = UserSqlBuilder.class, method = UPDATE_BY_PRIMARY_KEY_SELECTIVE)
    int updateByPrimaryKeySelective(User record);

    @Select("<script>\n" +
            "select * from user\n" +
            WHERE_SEGMENT +
            "</script>")
    List<User> selectByExample(@Param("example") Example example);

    @SelectProvider(type = UserSqlBuilder.class, method = SELECT_BY_QUERY)
    List<User> selectByQuery(Class clazz, @Param("query") UserQuery query, String orderBy);

    @SelectProvider(type = UserSqlBuilder.class, method = SELECT_PAGE_BY_QUERY)
    List<User> selectPageByQuery(Class clazz, @Param("query") UserQuery query, Page page);

    @SelectProvider(type = UserSqlBuilder.class, method = COUNT_BY_QUERY)
    long countByQuery(@Param("query") UserQuery query);
}


text:
RMines.Field = new Class(Observer, {
  EVENTS: $w('change reset loose win'),

  Options: {
    // the field sizes
    Sizes: {
      small:   '8x8',
      average: '16x8',
      normal:  '16x16',
      big:     '24x16',
      king:    '32x16'
    },

    // cells per mine concentration
    Levels: {
      easy:    9,
      normal:  6,
      hard:    3
    }
  },

  state: 'new',

  /**
   * Basic constructor
   */
  initialize: function() {
    this.$super();
    this.element = $E('div', {'class': 'field'})
      .onMousedown(this.click.bind(this))
      .onContextmenu('stopEvent');

    this.onWin('showAnimation', 'marked').onLoose('showAnimation', 'blown');
  },

  /**
   * Resets the field
   *
   * @param RMines.Controls controls
   * @return this;
   */
  reset: function(controls) {
    this.size    = this.Options.Sizes[controls.size.value]   || '8x8';
    this.level   = this.Options.Levels[controls.level.value] || 9;
    this.state   = 'new';
    this.marked  = 0;
    this.overall = 0;

    this.resize(controls).rebuild();

    return this.fire('reset');
  },

  /**
   * Changes the visual block size on the field
   *
   * @param RMines.Controls controls
   * @return this;
   */
  resize: function(controls) {
    this.element.setClass('field '+ (controls.blocks.value || 'normal'));
    return this;
  },

// protected

  /**
   * catches the clicks on the field
   *
   * @param Event click
   * @return void
   */
  click: function(event) {
    var cell = event.target;

    if (cell.pos) {
      event.stop();

      if (this.state == 'new') this.generate(cell);

      if (this.state == 'working') {
        this[(event.which == 3 || event.shiftKey) ? 'mark' : 'check'](cell);
        this.checkState(cell).fire('change');
      }
    }
  },

  /**
   * tries to check the cell
   *
   * @param Element cell
   * @return void
   */
  check: function(cell) {
    if (!cell.marked) {
      if (!cell.open) {
        cell.addClass('open').open = true;

        if (cell.mined) {
          cell.addClass('blown').blown = true;
        } else if (cell.mines == 0) {
          this.neighbors(cell).each(this.check, this);
        }
      } else if (cell.mines > 0) {
        // cheat mode, if all the hidden neighbors have no mines, open them up
        var neighbors = this.neighbors(cell),
          closed = neighbors.filter(function(c) { return !c.open && !c.marked; }),
          mined  = closed.filter('mined');

        if (mined.empty()) {
          closed.each(this.check, this);
        }
      }
    }
  },

  /**
   * Marks/unmarks the cell as mined
   *
   * @param Element cell
   * @return void
   */
  mark: function(cell) {
    if (!cell.open) {
      cell.marked = cell.toggleClass('marked').hasClass('marked');
      this.marked += cell.marked ? 1 : -1;

    }
  },

  /**
   * rebuilds the field
   *
   * @return void
   */
  rebuild: function() {
    var size = this.size.split('x').map('toInt');

    this.element.clean();
    this.grid   = [];
    this.cells  = [];
    this.width  = size[0];
    this.height = size[1];
    this.overall = (this.width * this.height / this.level).floor();

    for (var y=0; y < this.height; y++) {
      for (var row = [], x=0; x < this.width; x++) {
        var cell = new Element('div', {pos: [x,y], html: ' ', mines: 0});
        row.push(cell);
        this.cells.push(cell);
      }

      this.grid.push(row);
      this.element.insert(new Element('div', {'class': 'row'}).insert(row));
    }

  },

  /**
   * distributes the mines around the field
   *
   * NOTE: creates a blank field so that the
   *       initial cell was always blank and the player
   *       had a nice first field
   *
   * @param Element initial cell
   * @return void
   */
  generate: function(initial_cell) {
    var blank_field = this.neighbors(initial_cell).concat([initial_cell]);
    blank_field.concat(blank_field.map(this.neighbors, this)).uniq();

    var targets = this.cells.without.apply(this.cells, blank_field);

    targets.shuffle().slice(0, this.overall).each('set', 'mined', true).each(function(cell) {
      this.neighbors(cell).each(function(cell) {
        if (!cell.mined)
          cell.mines ++;
      });
    }, this);

    this.cells.each(function(cell) {
      if (cell.mines > 0) cell.addClass('mines-'+cell.mines).innerHTML = cell.mines + '';
    });

    this.state = 'working';
  },

  /**
   * finds the cell neighbors
   *
   * @param Element cell
   * @return Array neighbors list
   */
  neighbors: function(cell) {
    var neighbors = [], cell_x = cell.pos[0], cell_y = cell.pos[1],
      height = this.height - 1, width = this.width - 1;

    for (var x, y, i=0; i < 9; i++) {
      x = cell_x + (i%3) - 1;
      y = cell_y + (i/3).floor() - 1;

      if (!(x < 0 || y < 0 || x > width || y > height || (cell_x == x && cell_y == y))) {
        neighbors.push(this.grid[y][x]);
      }
    }

    return neighbors;
  },

  /**
   * Checks the game status
   *
   * @return this
   */
  checkState: function(target_cell) {
    for (var finished = true, has_blown = false, cell, len = this.cells.length, i=0; i < len; i++) {
      cell = this.cells[i];
      if (cell.blown) {
        has_blown = true;
        break;
      } else if (!cell.marked && !cell.open) {
        finished = false;
      }
    }

    if (has_blown) {
      this.state = 'looser';
      this.fire('loose', target_cell);
    } else if (finished) {
      this.state = 'winner';
      this.fire('win', target_cell);
    }

    return this;
  },

  /**
   * Shows the final animation starting from the cell
   *
   * @param String animation type
   * @param Element the last clicked cells
   * @return void
   */
  showAnimation: function(type, last_cell) {
    var fx_duration   = 400,
        fx_width      = 1.2,
        cell_x        = last_cell.pos[0],
        cell_y        = last_cell.pos[1],
        half_width    = this.width/2,
        half_height   = this.height/2,
        x_distance    = cell_x > half_width  ? cell_x + 1 : half_width.round(),
        y_distance    = cell_y > half_height ? cell_y + 1 : half_height.round(),
        distance      = x_distance < y_distance ? y_distance : x_distance,
        step_timeout  = fx_duration / distance,
        step_duration = step_timeout * fx_width;

    var start_fx = function(cell, class_name) {
      cell.className = class_name;
    };

    var end_fx   = function(cell, class_name) {
      cell.className = class_name;
      if (cell.marked && !cell.mined) {
        cell.removeClass('marked').addClass('wrong');
      } else if (cell.mined && !cell.blown && !cell.marked) {
        cell.addClass('mined');
      } else if (!cell.marked && !cell.blown) {
        cell.addClass('open');
      }
    };

    for (var y=0; y < this.height; y++) {
      for (var x=0; x < this.width; x++) {
        var x_diff  = (x - cell_x).abs(),
            y_diff  = (y - cell_y).abs(),
            diff    = x_diff < y_diff ? y_diff : x_diff,
            timeout = diff * step_timeout,
            cell    = this.grid[y][x];

        start_fx.delay(timeout, cell, type);
        end_fx.delay(timeout + step_duration, cell, cell.className);
      }
    }
  }
});


text:
package com.lumos;

import java.util.ArrayList;

public class Game {
	private static Game instance;

	private Player player;

	private MainWindow mainWindow;
	private InventoryWindow inventoryWindow;
	private StatWindow statWindow;

	private ArrayList<Window> windows;

	public static Game getInstance() {
		if (instance == null) {
			instance = new Game();
		}
		return instance;
	}

	private Game() {
		mainWindow = new MainWindow(640, 480, 87, 25, 0, 0);
		inventoryWindow = new InventoryWindow(300, 150, 39, 6, 645, 0);
		statWindow = new StatWindow(300, 325,39,16, 645, 155);

		windows = new ArrayList<Window>();
		windows.add(mainWindow);
		windows.add(inventoryWindow);
		windows.add(statWindow);

		player = new Player(10, "Player 1");
		player.setX((int) Math.floor(mainWindow.getCharWidth()/2));
		player.setY((int) Math.floor(mainWindow.getCharHeight()/2));
	}

	public void initWindows() {
		for (Window window : windows) {
			window.initUI();
		}
		mainWindow.toFront();
	}

	public Player getPlayer() {
		return player;
	}
}


text:
const DynamodbEvent = require('../../../lib/middleware/dynamodbEvent/dynamodbEvent.js');

describe('DynamodbEvent', () => {
	it('Test DynamodbEvent instance', () => {
		//TODO
	});
});


text:
package org.apereo.cas.config;

import com.google.common.collect.ImmutableSet;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.config.PersistenceConfiguration;
import net.sf.ehcache.distribution.RMIBootstrapCacheLoader;
import net.sf.ehcache.distribution.RMISynchronousCacheReplicator;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.configuration.support.Beans;
import org.apereo.cas.ticket.registry.EhCacheTicketRegistry;
import org.apereo.cas.ticket.registry.TicketRegistry;
import org.apereo.cas.util.ResourceUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.ehcache.EhCacheFactoryBean;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

/**
 * This is {@link EhcacheTicketRegistryConfiguration}.
 *
 * @author Misagh Moayyed
 * @since 5.0.0
 */
@Configuration("ehcacheTicketRegistryConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class EhcacheTicketRegistryConfiguration {

    @Autowired
    private CasConfigurationProperties casProperties;

    @RefreshScope
    @Bean
    public RMISynchronousCacheReplicator ticketRMISynchronousCacheReplicator() {

        return new RMISynchronousCacheReplicator(
                casProperties.getTicket().getRegistry().getEhcache().isReplicatePuts(),
                casProperties.getTicket().getRegistry().getEhcache().isReplicatePutsViaCopy(),
                casProperties.getTicket().getRegistry().getEhcache().isReplicateUpdates(),
                casProperties.getTicket().getRegistry().getEhcache().isReplicateUpdatesViaCopy(),
                casProperties.getTicket().getRegistry().getEhcache().isReplicateRemovals());
    }

    @RefreshScope
    @Bean
    public RMIBootstrapCacheLoader ticketCacheBootstrapCacheLoader() {
        return new RMIBootstrapCacheLoader(casProperties.getTicket().getRegistry().getEhcache().isLoaderAsync(),
                casProperties.getTicket().getRegistry().getEhcache().getMaxChunkSize());
    }

    @Lazy
    @Bean
    public EhCacheManagerFactoryBean cacheManager() {
        final EhCacheManagerFactoryBean bean = new EhCacheManagerFactoryBean();
        bean.setConfigLocation(ResourceUtils.prepareClasspathResourceIfNeeded(
                casProperties.getTicket().getRegistry().getEhcache().getConfigLocation()));
        bean.setShared(casProperties.getTicket().getRegistry().getEhcache().isShared());
        bean.setCacheManagerName(casProperties.getTicket().getRegistry().getEhcache().getCacheManagerName());

        return bean;
    }

    @Lazy
    @Bean
    public EhCacheFactoryBean ehcacheTicketsCache(@Qualifier("cacheManager")
                                                  final CacheManager manager) {
        final EhCacheFactoryBean bean = new EhCacheFactoryBean();
        bean.setCacheName(casProperties.getTicket().getRegistry().getEhcache().getCacheName());
        bean.setCacheEventListeners(ImmutableSet.of(ticketRMISynchronousCacheReplicator()));
        bean.setTimeToIdle(casProperties.getTicket().getRegistry().getEhcache().getCacheTimeToIdle());
        bean.setTimeToLive(casProperties.getTicket().getRegistry().getEhcache().getCacheTimeToLive());

        bean.setCacheManager(manager);
        bean.setBootstrapCacheLoader(ticketCacheBootstrapCacheLoader());
        bean.setDiskExpiryThreadIntervalSeconds(
                casProperties.getTicket().getRegistry().getEhcache().getDiskExpiryThreadIntervalSeconds());

        bean.setEternal(casProperties.getTicket().getRegistry().getEhcache().isEternal());
        bean.setMaxEntriesLocalHeap(casProperties.getTicket().getRegistry().getEhcache().getMaxElementsInMemory());
        bean.setMaxEntriesInCache(casProperties.getTicket().getRegistry().getEhcache().getMaxElementsInCache());
        bean.setMaxEntriesLocalDisk(casProperties.getTicket().getRegistry().getEhcache().getMaxElementsOnDisk());
        bean.setMemoryStoreEvictionPolicy(casProperties.getTicket().getRegistry().getEhcache().getMemoryStoreEvictionPolicy());

        final PersistenceConfiguration c = new PersistenceConfiguration();
        c.strategy(casProperties.getTicket().getRegistry().getEhcache().getPersistence());
        c.setSynchronousWrites(casProperties.getTicket().getRegistry().getEhcache().isSynchronousWrites());
        bean.persistence(c);

        return bean;
    }

    @RefreshScope
    @Bean(name = {"ehcacheTicketRegistry", "ticketRegistry"})
    public TicketRegistry ehcacheTicketRegistry(@Qualifier("ehcacheTicketsCache")
                                                final Cache ehcacheTicketsCache) {
        final EhCacheTicketRegistry r = new EhCacheTicketRegistry(ehcacheTicketsCache);
        r.setCipherExecutor(Beans.newTicketRegistryCipherExecutor(
                casProperties.getTicket().getRegistry().getEhcache().getCrypto()
        ));
        return r;
    }
}


text:
<!DOCTYPE HTML>

    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <title>klass tests</title>
    <link rel="stylesheet" href="../node_modules/sink-test/src/sink.css" type="text/css" media="screen" title="no title" charset="utf-8">

Klass tests


text:
title: navbar
published: true
process:
    markdown: true
    twig: false
routable: true
cache_enable: true
visible: true
items:
    1:
        title: News
        subtitle: 'Company News'
        url: '/#company_news'
        icon: newspaper-o
        fore_color: ''
        back_color: ''
        li_class: nav_menu_front_page
        anchor_class: ''
    2:
        title: Product
        subtitle: 'Releases and Sales'
        url: '/#product_releases'
        icon: shopping-basket
        fore_color: ''
        back_color: ''
        li_class: nav_menu_front_page
        anchor_class: ''
    3:
        title: 'Site Updates'
        subtitle: ''
        url: '/#site_updates'
        icon: puzzle-piece
        fore_color: ''
        back_color: ''
        li_class: nav_menu_front_page
        anchor_class: ''
    4:
        title: Back
        subtitle: ''
        url: '/cardstack/#'
        icon: mail-reply
        fore_color: ''
        back_color: ''
        li_class: 'nav_menu_child_menu hidden'
        anchor_class: ''
child_type: default
---


text:
@implementation NSObject (MTKObserving)

#pragma mark Internal

/// Getter for dictionary containing all registered observers for this object. Keys are observed key-paths.
- (NSMutableDictionary *)mtk_keyPathBlockObservers {
    // Observer is hidden object that has target (this object), key path and owner.
    // There should never exist two or more observers with the same target, key path and owner.
    // Observer has multiple observation block which are executed in order they were added.
    static char associationKey;
    NSMutableDictionary *keyPathObservers = objc_getAssociatedObject(self, &associationKey);
    if ( ! keyPathObservers) {
        keyPathObservers = [[NSMutableDictionary alloc] init];
        objc_setAssociatedObject(self,
                                 &associationKey,
                                 keyPathObservers,
                                 OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return keyPathObservers;
}

/// Find existing observer or create new for this key-path and owner. Multiple uses of one key-path per owner return the same observer.
- (MTKObserver *)mtk_observerForKeyPath:(NSString *)keyPath owner:(id)owner {
	MTKObserver *observer = nil;
    // Key path is used as key to retrieve observer.
	// For one key-path may be more observers with different owners.

    // Obtain the set
    NSMutableSet *observersForKeyPath = [[self mtk_keyPathBlockObservers] objectForKey:keyPath];
	if ( ! observersForKeyPath) {
        // Nothing found for this key-path
		observersForKeyPath = [[NSMutableSet alloc] init];
		[[self mtk_keyPathBlockObservers] setObject:observersForKeyPath forKey:keyPath];
	}
	else {
        // Find the one with this owner
		for (MTKObserver *existingObserver in observersForKeyPath) {
			if (existingObserver.owner == owner) {
				observer = existingObserver;
				break;
			}
		}
	}
    // Now the observer itself
	if ( ! observer) {
		observer = [[MTKObserver alloc] initWithTarget:self keyPath:keyPath owner:owner];
        [observersForKeyPath addObject:observer];
        [observer attach];
    }
    return observer;
}

/// Getter for set containing all registered notification observers for this object. See `NSNotificationCenter`.
- (NSMutableSet *)mtk_notificationBlockObservers {
    static char associationKey;
    NSMutableSet *notificationObservers = objc_getAssociatedObject(self, &associationKey);
    if ( ! notificationObservers) {
        notificationObservers = [[NSMutableSet alloc] init];
        objc_setAssociatedObject(self,
                                 &associationKey,
                                 notificationObservers,
                                 OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return notificationObservers;
}

/// Called internally by the owner.
- (void)mtk_removeAllObservationsForOwner:(id)owner {
	for (NSMutableSet *observersForKeyPath in [[self mtk_keyPathBlockObservers] allValues]) {
		for (MTKObserver *observer in [observersForKeyPath copy]) {
			if (observer.owner == owner) {
				[observer detach];
				[observersForKeyPath removeObject:observer];
			}
		}
	}
}

#pragma mark Observe Properties

- (void)observeProperty:(NSString *)keyPath withBlock:(MTKBlockChange)observationBlock {
    [self observeObject:self property:keyPath withBlock:^(__weak id weakSelf, __weak id weakObject, id old, id new) {
        // weakSelf and weakObject are the same
        observationBlock(weakSelf, old, new);
    }];
}

- (void)observeProperties:(NSArray *)keyPaths withBlock:(MTKBlockChangeMany)observationBlock {
    [self observeObject:self properties:keyPaths withBlock:^(__weak id weakSelf, __weak id weakObject, NSString *keyPath, id old, id new) {
        // weakSelf and weakObject are the same
        observationBlock(weakSelf, keyPath, old, new);
    }];
}

- (void)observeProperty:(NSString *)keyPath withSelector:(SEL)observationSelector {
	[self observeObject:self property:keyPath withSelector:observationSelector];
}

- (void)observeProperties:(NSArray *)keyPaths withSelector:(SEL)observationSelector {
    [self observeObject:self properties:keyPaths withSelector:observationSelector];
}

#pragma mark Foreign Property

/// Add observation block to appropriate observer.
- (void)observeObject:(id)object property:(NSString *)keyPath withBlock:(MTKBlockForeignChange)observationBlock {
    __weak typeof(self) weakSelf = self;
	MTKObserver *observer = [object mtk_observerForKeyPath:keyPath owner:self];
	[observer addSettingObservationBlock:^(__weak id weakObject, id old, id new) {
        observationBlock(weakSelf, weakObject, old, new);
    }];
}

/// Register the block for all given key-paths.
- (void)observeObject:(id)object properties:(NSArray *)keyPaths withBlock:(MTKBlockForeignChangeMany)observationBlock {
	for (NSString *keyPath in keyPaths) {
        NSString *keyPathCopy = [keyPath copy]; // If some fool uses mutable key-paths
        [self observeObject:object property:keyPath withBlock:^(__weak id weakSelf, __weak id weakObject, id old , id new){
            observationBlock(weakSelf, weakObject, keyPathCopy, old, new);
        }];
    }
}

/// Register block invoking given selector. Smart detecting of number of arguments.
- (void)observeObject:(id)object property:(NSString *)keyPath withSelector:(SEL)observationSelector {
	NSMethodSignature *signature = [self methodSignatureForSelector:observationSelector];
    NSInteger numberOfArguments = [signature numberOfArguments];
	[self observeObject:object property:keyPath withBlock:^(__weak id weakSelf, __weak id weakObject, id old, id new) {
		switch (numberOfArguments) {
            case 0:
            case 1:
                [NSException raise:NSInternalInconsistencyException format:@"WTF?! Method should have at least two arguments: self and _cmd!"];
                break;

            case 2: // +0
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
                // -someObjectDidChangeSomething
                [weakSelf performSelector:observationSelector];
                break;

            case 3: // +1
                if (weakSelf == weakObject) {
                    // -didChangeSomethingTo:
                    [weakSelf performSelector:observationSelector withObject:new]; // Observing self, we dont need self
                }
                else {
                    // -someObjectDidChangeSomething:
                    [weakSelf performSelector:observationSelector withObject:weakObject]; // Observing another object
                }
                break;

			case 4: // +2
                if (weakSelf == weakObject) {
                    // -didChangeSomethingFrom:to:
                    [weakSelf performSelector:observationSelector withObject:old withObject:new];
                }
				else {
                    // -someObject: didChangeSomethingTo:
                    [weakSelf performSelector:observationSelector withObject:weakObject withObject:new];
                }
                break;
#pragma clang diagnostic pop

            default: {
                // +3
                // -someObject:didChangeSomethingFrom:to:
                void(*msgSend)(id, SEL, id, id, id) = (typeof(msgSend))objc_msgSend;
                msgSend(weakSelf, observationSelector, weakObject, old, new);
                break;
            }
        }
	}];
}

/// Register the selector for each key-path.
- (void)observeObject:(id)object properties:(NSArray *)keyPaths withSelector:(SEL)observationSelector {
	for (NSString *keyPath in keyPaths) {
        [self observeObject:object property:keyPath withSelector:observationSelector];
    }
}

#pragma mark Observe Relationships

/// Add observation blocks to appropriate observer. If some block was not specified, use the `changeBlock`.
- (void)observeRelationship:(NSString *)keyPath
                changeBlock:(MTKBlockChange)changeBlock
             insertionBlock:(MTKBlockInsert)insertionBlock
               removalBlock:(MTKBlockRemove)removalBlock
           replacementBlock:(MTKBlockReplace)replacementBlock
{
    MTKObserver *observer = [self mtk_observerForKeyPath:keyPath owner:self];
    [observer addSettingObservationBlock:changeBlock];
    [observer addInsertionObservationBlock: insertionBlock ?: ^(__weak id weakSelf, id new, NSIndexSet *indexes) {
        // If no insertion block was specified, call general change block.
        changeBlock(weakSelf, nil, [weakSelf valueForKeyPath:keyPath]);
    }];
    [observer addRemovalObservationBlock: removalBlock ?: ^(__weak id weakSelf, id old, NSIndexSet *indexes) {
        // If no removal block was specified, call general change block.
        changeBlock(weakSelf, nil, [weakSelf valueForKeyPath:keyPath]);
    }];
    [observer addReplacementObservationBlock: replacementBlock ?: ^(__weak id weakSelf, id old, id new, NSIndexSet *indexes) {
        // If no removal block was specified, call general change block.
        changeBlock(weakSelf, nil, [weakSelf valueForKeyPath:keyPath]);
    }];
}

/// Call main `-observeRelationship:...` method with only first argument.
- (void)observeRelationship:(NSString *)keyPath changeBlock:(MTKBlockGeneric)changeBlock {
    [self observeRelationship:keyPath
                  changeBlock:^(__weak id weakSelf, id old, id new) {
                      changeBlock(weakSelf, new);
                  }
               insertionBlock:nil
                 removalBlock:nil
             replacementBlock:nil];
}

#pragma mark Map Properties

/// Call `-map:to:transform:` with transform block that uses returns the same value, or null replacement.
- (void)map:(NSString *)sourceKeyPath to:(NSString *)destinationKeyPath null:(id)nullReplacement {
    [self map:sourceKeyPath to:destinationKeyPath transform:^id(id value) {
        return value ?: nullReplacement;
    }];
}

/// Observe source key-path and set its new value to destination every time it changes. Use transformation block, if specified.
- (void)map:(NSString *)sourceKeyPath to:(NSString *)destinationKeyPath transform:(id (^)(id))transformationBlock {
    [self observeProperty:sourceKeyPath withBlock:^(__weak id weakSelf, id old, id new) {
        id transformedValue = (transformationBlock? transformationBlock(new) : new);
        [weakSelf setValue:transformedValue forKeyPath:destinationKeyPath];
    }];
}

#pragma mark Notifications

/// Call another one.
- (void)observeNotification:(NSString *)name withBlock:(MTKBlockNotify)block {
	[self observeNotification:name fromObject:nil withBlock:block];
}

/// Add block observer on current operation queue and the resulting internal opaque observe is stored in associated mutable set.
- (void)observeNotification:(NSString *)name fromObject:(id)object withBlock:(MTKBlockNotify)block {
	__weak typeof(self) weakSelf = self;
    // Invoke manually for the first time.
    block(weakSelf, nil);
	id internalObserver = [[NSNotificationCenter defaultCenter] addObserverForName:name
																			object:object
																			 queue:[NSOperationQueue currentQueue]
																		usingBlock:^(NSNotification *notification) {
																			block(weakSelf, notification);
																		}];
	[[self mtk_notificationBlockObservers] addObject:internalObserver];
}

/// Make all combination of name and object (if any are given) and call main notification observing method.
- (void)observeNotifications:(NSArray *)names fromObjects:(NSArray *)objects withBlock:(MTKBlockNotify)block {
	for (NSString *name in names) {
		if (objects) {
			for (id object in objects) {
				[self observeNotification:name fromObject:object withBlock:block];
			}
		}
		else {
			[self observeNotification:name fromObject:nil withBlock:block];
		}
	}
}

#pragma Removing

/// Called usually from dealloc (may be called at any time). Detach all observers. The associated objects are released once the deallocation process finishes.
- (void)removeAllObservations {
	// Key-Path Observers
    NSMutableDictionary *keyPathBlockObservers = [self mtk_keyPathBlockObservers];
	for (NSMutableSet *observersForKeyPath in [[self mtk_keyPathBlockObservers] allValues]) {
        [observersForKeyPath makeObjectsPerformSelector:@selector(detach)];
        [observersForKeyPath removeAllObjects];
	}
    [keyPathBlockObservers removeAllObjects];

    // NSNotification Observers
	NSMutableSet *notificationObservers = [self mtk_notificationBlockObservers];
	for (id internalObserver in notificationObservers) {
		[[NSNotificationCenter defaultCenter] removeObserver:internalObserver];
	}
	[notificationObservers removeAllObjects];
}

/// Called at any time, tell the observed object to remove our observation blocks.
- (void)removeAllObservationsOfObject:(id)object {
	[object mtk_removeAllObservationsForOwner:self];
}

@end

MTKMappingTransformBlock const MTKMappingIsNilBlock = ^NSNumber *(id value){
    return @( value == nil );
};

MTKMappingTransformBlock const MTKMappingIsNotNilBlock = ^NSNumber *(id value){
    return @( value != nil );
};

MTKMappingTransformBlock const MTKMappingInvertBooleanBlock = ^NSNumber *(NSNumber *value){
    return @( ! value.boolValue );
};

MTKMappingTransformBlock const MTKMappingURLFromStringBlock = ^NSURL *(NSString *value){
    return [NSURL URLWithString:value];
};


text:
"use strict";

var referee = require("@sinonjs/referee");

referee.add("spy", {
    assert: function(obj) {
        return obj !== null && typeof obj.calledWith === "function" && !obj.returns;
    },
    assertMessage: "Expected object ${0} to be a spy function",
    refuteMessage: "Expected object ${0} not to be a spy function"
});

referee.add("stub", {
    assert: function(obj) {
        return obj !== null && typeof obj.calledWith === "function" && typeof obj.returns === "function";
    },
    assertMessage: "Expected object ${0} to be a stub function",
    refuteMessage: "Expected object ${0} not to be a stub function"
});

referee.add("mock", {
    assert: function(obj) {
        return obj !== null && typeof obj.verify === "function" && typeof obj.expects === "function";
    },
    assertMessage: "Expected object ${0} to be a mock",
    refuteMessage: "Expected object ${0} not to be a mock"
});

referee.add("fakeServer", {
    assert: function(obj) {
        return (
            obj !== null &&
            Object.prototype.toString.call(obj.requests) === "[object Array]" &&
            typeof obj.respondWith === "function"
        );
    },
    assertMessage: "Expected object ${0} to be a fake server",
    refuteMessage: "Expected object ${0} not to be a fake server"
});

referee.add("clock", {
    assert: function(obj) {
        return obj !== null && typeof obj.tick === "function" && typeof obj.setTimeout === "function";
    },
    assertMessage: "Expected object ${0} to be a clock",
    refuteMessage: "Expected object ${0} not to be a clock"
});