<commit_before>/**
 * @license
 * Copyright 2014 The Lovefield Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
goog.setTestOnly();
goog.require('goog.testing.AsyncTestCase');
goog.require('goog.testing.jsunit');
goog.require('hr.db');
goog.require('lf.fn');
goog.require('lf.schema.DataStoreType');
goog.require('lf.testing.hrSchema.JobDataGenerator');
goog.require('lf.testing.hrSchema.MockDataGenerator');
goog.require('lf.testing.util');

/** @type {!goog.testing.AsyncTestCase} */
var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall(
    'EndToEndTransactionTest');

/** @type {number} */
asyncTestCase.stepTimeout = 5 * 1000;  // 5 seconds

/** @private {!lf.Database} */
var db;

/** @type {!hr.db.schema.Employee} */
var e;

/** @type {!hr.db.schema.Job} */
var j;

/** @type {!hr.db.schema.Department} */
var d;

/** @type {!Array<!hr.db.row.Job>} */
var sampleJobs;

/** @type {!Array<!hr.db.row.Employee>} */
var sampleEmployees;

/** @type {!Array<!hr.db.row.Department>} */
var sampleDepartments;

/** @type {!lf.testing.hrSchema.MockDataGenerator} */
var dataGenerator;

/** @type {!lf.Global} */
var global;

/** @type {!lf.Transaction} */
var tx;

function setUp() {
  asyncTestCase.waitForAsync('setUp');
  hr.db.connect({storeType: lf.schema.DataStoreType.MEMORY}).then(function(
      database) {
        db = database;
        j = db.getSchema().getJob();
        e = db.getSchema().getEmployee();
        d = db.getSchema().getDepartment();
        global = hr.db.getGlobal();
        dataGenerator = new lf.testing.hrSchema.MockDataGenerator(
            /** @type {!hr.db.schema.Database} */ (db.getSchema()));

        tx = db.createTransaction();
        return addSampleData();
      }).then(function() {
    asyncTestCase.continueTesting();
  }, fail);
}

/**
 * Populates the database with sample data.
 * @return {!IThenable} A signal firing when the data has been added.
 */
function addSampleData() {
  dataGenerator.generate(
      /* jobCount */ 50,
      /* employeeCount */ 300,
      /* departmentCount */ 10);
  sampleJobs = dataGenerator.sampleJobs;
  sampleEmployees = dataGenerator.sampleEmployees;
  sampleDepartments = dataGenerator.sampleDepartments;

  var c = db.getSchema().getCountry();
  var l = db.getSchema().getLocation();
  var r = db.getSchema().getRegion();

  return db.createTransaction().exec([
    db.insert().into(r).values(dataGenerator.sampleRegions),
    db.insert().into(c).values(dataGenerator.sampleCountries),
    db.insert().into(l).values(dataGenerator.sampleLocations),
    db.insert().into(d).values(sampleDepartments),
    db.insert().into(j).values(sampleJobs),
    db.insert().into(e).values(sampleEmployees)
  ]);
}

function commitFn() { tx.commit(); }
function rollbackFn() { tx.rollback(); }
function attachFn() { tx.attach(db.select().from(j)); }
function beginFn() { tx.begin([j, e]); }
function execFn() { tx.exec([db.select().from(e)]); }

/**
 * Tests that an lf.Exception.TRANSACTION is thrown when the following
 * operations are requested before the transaction has started initializing.
 *  - Attaching a query.
 *  - Attempting to commit the transaction.
 *  - Attempting to rollback the transaction.
 */
function testThrows_StateCreated() {
  // 107: Invalid transaction state transition: {0} -> {1}.
  lf.testing.util.assertThrowsError(107, attachFn);
  lf.testing.util.assertThrowsError(107, commitFn);
  lf.testing.util.assertThrowsError(107, rollbackFn);
}

/**
 * Tests that an lf.Exception.TRANSACTION is thrown when any operation is
 * attempted while a query is executing.
 */
function testThrows_StateExecutingQuery() {
  asyncTestCase.waitForAsync('testThrows_StateExecutingQuery');

  // 107: Invalid transaction state transition: {0} -> {1}.
  tx.begin([j, e]).then(function() {
    tx.attach(db.select().from(e));

    lf.testing.util.assertThrowsError(107, attachFn);
    lf.testing.util.assertThrowsError(107, beginFn);
    lf.testing.util.assertThrowsError(107, commitFn);
    lf.testing.util.assertThrowsError(107, rollbackFn);
    lf.testing.util.assertThrowsError(107, execFn);
    asyncTestCase.continueTesting();
  }, fail);
}

/**
 * Tests that an lf.Exception.TRANSACTION is thrown when any operation is
 * attempted after transaction has been finalized.
 */
function testThrows_StateFinalized() {
  asyncTestCase.waitForAsync('testThrows_StateFinalized');

  // 107: Invalid transaction state transition: {0} -> {1}.
  tx.begin([e]).then(function() {
    var whenDone = tx.commit();
    lf.testing.util.assertThrowsError(107, beginFn);
    lf.testing.util.assertThrowsError(107, attachFn);
    lf.testing.util.assertThrowsError(107, commitFn);
    lf.testing.util.assertThrowsError(107, rollbackFn);
    lf.testing.util.assertThrowsError(107, execFn);

    return whenDone;
  }).then(function() {
    asyncTestCase.continueTesting();
  }, fail);
}

/**
 * Tests that an lf.Exception.TRANSACTION is thrown when any operation is
 * attempted while a transaction is still initializing.
 */
function testThrows_StateAcquiringScope() {
  asyncTestCase.waitForAsync('testThrows_StateAcquiringScope');
  var whenDone = tx.begin([e]);
  // 107: Invalid transaction state transition: {0} -> {1}.
  lf.testing.util.assertThrowsError(107, beginFn);
  lf.testing.util.assertThrowsError(107, attachFn);
  lf.testing.util.assertThrowsError(107, commitFn);
  lf.testing.util.assertThrowsError(107, rollbackFn);
  lf.testing.util.assertThrowsError(107, execFn);

  whenDone.then(function() {
    asyncTestCase.continueTesting();
  }, fail);
}

/**
 * Tests that an lf.Exception.TRANSACTION is thrown when a set of queries that
 * will be automatically committed (no need to call commit), is in progress.
 */
function testThrows_StateExecutingAndCommitting() {
  asyncTestCase.waitForAsync('testThrows_StateExecutingAndCommitting');
  var whenDone = tx.exec([db.select().from(e)]);
  // 107: Invalid transaction state transition: {0} -> {1}.
  lf.testing.util.assertThrowsError(107, beginFn);
  lf.testing.util.assertThrowsError(107, attachFn);
  lf.testing.util.assertThrowsError(107, commitFn);
  lf.testing.util.assertThrowsError(107, rollbackFn);
  lf.testing.util.assertThrowsError(107, execFn);

  whenDone.then(function() {
    asyncTestCase.continueTesting();
  }, fail);
}

function testExec() {
  asyncTestCase.waitForAsync('testExec');
  var tx = db.createTransaction();
  var q1 = db.select(lf.fn.count(j.id).as('jid')).from(j);
  var q2 = db.select(lf.fn.count(d.id).as('did')).from(d);
  var q3 = db.delete().from(j);
  tx.exec([q1, q2, q3, q1]).then(function(results) {
    assertEquals(4, results.length);
    assertEquals(sampleJobs.length, results[0][0]['jid']);
    assertEquals(sampleDepartments.length, results[1][0]['did']);
    assertEquals(0, results[3][0]['jid']);
    asyncTestCase.continueTesting();
  }, fail);
}

function testAttach_Success() {
  asyncTestCase.waitForAsync('testAttach_Success');

  var scope = [j, e];
  tx.begin(scope).then(function() {
    var q1 = db.select().from(j);
    return tx.attach(q1);
  }).then(function(results) {
    assertEquals(sampleJobs.length, results.length);

    var q2 = db.select().from(e);
    return tx.attach(q2);
  }).then(function(results) {
    assertEquals(sampleEmployees.length, results.length);

    var hireDate = dataGenerator.employeeGroundTruth.maxHireDate;
    var q3 = db.
        delete().
        from(e).
        where(e.hireDate.eq(hireDate));
    return tx.attach(q3);
  }).then(function() {
    var q4 = db.select().from(e);
    return tx.attach(q4);
  }).then(function(results) {
    assertTrue(results.length < sampleEmployees.length);

    // Deleting all rows in the Job table.
    var q5 = db.delete().from(j);
    return tx.attach(q5);
  }).then(function() {
    var q6 = db.select().from(j);
    return tx.attach(q6);
  }).then(function(results) {
    // Expecting all rows to have been deleted within tx's context.
    assertEquals(0, results.length);

    // Expecting all job rows to *not* have been deleted from disk yet, since
    // the transaction has not been committed.
    return lf.testing.util.selectAll(global, j);
  }).then(function(results) {
    assertEquals(sampleJobs.length, results.length);

    return tx.commit();
  }).then(function() {
    // Expecting all job rows to have been deleted from disk, now that the
    // transaction was committed.
    return lf.testing.util.selectAll(global, j);
  }).then(function(results) {
    assertEquals(0, results.length);

    // Expecting all locks to have been released by previous transaction, which
    // should allow the following query to complete.
    return db.select().from(e).exec();
  }).then(function(results) {
    assertTrue(results.length < sampleEmployees.length);
    asyncTestCase.continueTesting();
  }, fail);
}

/**
 * Tests that if an attached query fails, the entire transaction is rolled back.
 */
function testAttach_Error() {
  asyncTestCase.waitForAsync('testAttach_Error');

  var scope = [j, e];
  var newJobId = 'SomeUniqueId';

  tx.begin(scope).then(function() {
    var q0 = db.select().from(j);
    return tx.attach(q0);
  }).then(function(results) {
    assertEquals(sampleJobs.length, results.length);

    // Adding a new job row.
    var newJob = j.createRow();
    newJob.setId(newJobId);
    var q1 = db.insert().into(j).values([newJob]);
    return tx.attach(q1);
  }).then(function() {
    var q2 = db.select().from(j).where(j.id.eq(newJobId));
    return tx.attach(q2);
  }).then(function(results) {
    assertEquals(1, results.length);

    var q3 = db.select().from(j);
    return tx.attach(q3);
  }).then(function(results) {
    assertEquals(sampleJobs.length + 1, results.length);

    // Attempting to add an employee row that already exists.
    var q4 = db.insert().into(e).values([sampleEmployees[0]]);
    return tx.attach(q4);
  }).thenCatch(function(e) {
    // 201: Duplicate keys are not allowed.
    assertEquals(201, e.code);

    // Checking that the transaction has been finalized.
    // 107: Invalid transaction state transition: {0} -> {1}.
    lf.testing.util.assertThrowsError(107, attachFn);
    lf.testing.util.assertThrowsError(107, commitFn);
    lf.testing.util.assertThrowsError(107, rollbackFn);
    lf.testing.util.assertThrowsError(107, beginFn);

    return lf.testing.util.selectAll(global, j);
  }).then(function(results) {
    // Checking that the entire transaction was rolled back, and therefore that
    // Job row that had been added does not appear on disk.
    assertEquals(sampleJobs.length, results.length);

    // Checking that all locks have been released, which will allow other
    // transactions referring to the same scope to execute successfully.
    return db.select().from(j).exec();
  }).then(function(results) {
    assertEquals(sampleJobs.length, results.length);
    asyncTestCase.continueTesting();
  });
}

/**
 * Tests that when a transaction is explicitly rolled back, all changes that
 * were made as part of this transaction are discarded.
 */
function testRollback() {
  asyncTestCase.waitForAsync('testRollback');

  var scope = [j, e];
  var newJobId = 'SomeUniqueId';

  tx.begin(scope).then(function() {
    // Adding a new job row.
    var newJob = j.createRow();
    newJob.setId(newJobId);
    var q1 = db.insert().into(j).values([newJob]);
    return tx.attach(q1);
  }).then(function(results) {
    var q2 = db.select().from(j).where(j.id.eq(newJobId));
    return tx.attach(q2);
  }).then(function(results) {
    assertEquals(1, results.length);

    var q3 = db.select().from(j);
    return tx.attach(q3);
  }).then(function(results) {
    assertEquals(sampleJobs.length + 1, results.length);

    return tx.rollback();
  }).then(function() {
    // Checking that the transaction has been finalized.
    // 107: Invalid transaction state transition: {0} -> {1}.
    lf.testing.util.assertThrowsError(107, attachFn);
    lf.testing.util.assertThrowsError(107, commitFn);
    lf.testing.util.assertThrowsError(107, rollbackFn);
    lf.testing.util.assertThrowsError(107, beginFn);

    return lf.testing.util.selectAll(global, j);
  }).then(function(results) {
    // Checking that the entire transaction was rolled back, and therefore that
    // Job row that had been added does not appear on disk.
    assertEquals(sampleJobs.length, results.length);

    // Expecting all locks to have been released by previous transaction, which
    // should allow the following query to complete.
    return db.select().from(j).exec();
  }).then(function() {
    asyncTestCase.continueTesting();
  });
}

/**
 * Tests the case where an attached query modifiess the results of an observed
 * query and ensures that observers are triggered.
 */
function testAttach_WithObservers() {
  asyncTestCase.waitForAsync('testAttach_WithObservers');
  var scope = [j];

  var initialJobCount = sampleJobs.length;
  var additionalJobCount = 2;

  var jobDataGenerator = new lf.testing.hrSchema.JobDataGenerator(
      hr.db.getSchema());
  var newJobs = jobDataGenerator.generate(additionalJobCount);
  newJobs.forEach(function(job, index) {
    job.setId('SomeUniqueId' + index.toString());
  });

  var observeCallback = function(changeEvents) {
    assertEquals(
        initialJobCount + additionalJobCount,
        changeEvents.length);
    assertEquals(
        initialJobCount + additionalJobCount,
        changeEvents[0]['object'].length);

    asyncTestCase.continueTesting();
  };

  var q = db.select().from(j);
  db.observe(q, observeCallback);

  tx.begin(scope).then(function() {
    // Adding a new job row.
    var q1 = db.insert().into(j).values([newJobs[0]]);
    return tx.attach(q1);
  }).then(function(results) {
    // Adding another new job row.
    var q2 = db.insert().into(j).values([newJobs[1]]);
    return tx.attach(q2);
  }).then(function() {
    return tx.commit();
  }, fail);
}
<commit_msg>Fixing foreign key constraint violations in end_to_end_transaction_test.js<commit_after>/**
 * @license
 * Copyright 2014 The Lovefield Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
goog.setTestOnly();
goog.require('goog.testing.AsyncTestCase');
goog.require('goog.testing.jsunit');
goog.require('hr.db');
goog.require('lf.fn');
goog.require('lf.schema.DataStoreType');
goog.require('lf.testing.hrSchema.JobDataGenerator');
goog.require('lf.testing.hrSchema.MockDataGenerator');
goog.require('lf.testing.util');

/** @type {!goog.testing.AsyncTestCase} */
var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall(
    'EndToEndTransactionTest');

/** @type {number} */
asyncTestCase.stepTimeout = 5 * 1000;  // 5 seconds

/** @private {!lf.Database} */
var db;

/** @type {!hr.db.schema.Employee} */
var e;

/** @type {!hr.db.schema.Job} */
var j;

/** @type {!hr.db.schema.Department} */
var d;

/** @type {!Array<!hr.db.row.Job>} */
var sampleJobs;

/** @type {!Array<!hr.db.row.Employee>} */
var sampleEmployees;

/** @type {!Array<!hr.db.row.Department>} */
var sampleDepartments;

/** @type {!lf.testing.hrSchema.MockDataGenerator} */
var dataGenerator;

/** @type {!lf.Global} */
var global;

/** @type {!lf.Transaction} */
var tx;

function setUp() {
  asyncTestCase.waitForAsync('setUp');
  hr.db.connect({storeType: lf.schema.DataStoreType.MEMORY}).then(function(
      database) {
        db = database;
        j = db.getSchema().getJob();
        e = db.getSchema().getEmployee();
        d = db.getSchema().getDepartment();
        global = hr.db.getGlobal();
        dataGenerator = new lf.testing.hrSchema.MockDataGenerator(
            /** @type {!hr.db.schema.Database} */ (db.getSchema()));

        tx = db.createTransaction();
        return addSampleData();
      }).then(function() {
    asyncTestCase.continueTesting();
  }, fail);
}

/**
 * Populates the database with sample data.
 * @return {!IThenable} A signal firing when the data has been added.
 */
function addSampleData() {
  dataGenerator.generate(
      /* jobCount */ 50,
      /* employeeCount */ 300,
      /* departmentCount */ 10);
  sampleJobs = dataGenerator.sampleJobs;
  sampleEmployees = dataGenerator.sampleEmployees;
  sampleDepartments = dataGenerator.sampleDepartments;

  var c = db.getSchema().getCountry();
  var l = db.getSchema().getLocation();
  var r = db.getSchema().getRegion();

  return db.createTransaction().exec([
    db.insert().into(r).values(dataGenerator.sampleRegions),
    db.insert().into(c).values(dataGenerator.sampleCountries),
    db.insert().into(l).values(dataGenerator.sampleLocations),
    db.insert().into(d).values(sampleDepartments),
    db.insert().into(j).values(sampleJobs),
    db.insert().into(e).values(sampleEmployees)
  ]);
}

function commitFn() { tx.commit(); }
function rollbackFn() { tx.rollback(); }
function attachFn() { tx.attach(db.select().from(j)); }
function beginFn() { tx.begin([j, e]); }
function execFn() { tx.exec([db.select().from(e)]); }

/**
 * Tests that an lf.Exception.TRANSACTION is thrown when the following
 * operations are requested before the transaction has started initializing.
 *  - Attaching a query.
 *  - Attempting to commit the transaction.
 *  - Attempting to rollback the transaction.
 */
function testThrows_StateCreated() {
  // 107: Invalid transaction state transition: {0} -> {1}.
  lf.testing.util.assertThrowsError(107, attachFn);
  lf.testing.util.assertThrowsError(107, commitFn);
  lf.testing.util.assertThrowsError(107, rollbackFn);
}

/**
 * Tests that an lf.Exception.TRANSACTION is thrown when any operation is
 * attempted while a query is executing.
 */
function testThrows_StateExecutingQuery() {
  asyncTestCase.waitForAsync('testThrows_StateExecutingQuery');

  // 107: Invalid transaction state transition: {0} -> {1}.
  tx.begin([j, e]).then(function() {
    tx.attach(db.select().from(e));

    lf.testing.util.assertThrowsError(107, attachFn);
    lf.testing.util.assertThrowsError(107, beginFn);
    lf.testing.util.assertThrowsError(107, commitFn);
    lf.testing.util.assertThrowsError(107, rollbackFn);
    lf.testing.util.assertThrowsError(107, execFn);
    asyncTestCase.continueTesting();
  }, fail);
}

/**
 * Tests that an lf.Exception.TRANSACTION is thrown when any operation is
 * attempted after transaction has been finalized.
 */
function testThrows_StateFinalized() {
  asyncTestCase.waitForAsync('testThrows_StateFinalized');

  // 107: Invalid transaction state transition: {0} -> {1}.
  tx.begin([e]).then(function() {
    var whenDone = tx.commit();
    lf.testing.util.assertThrowsError(107, beginFn);
    lf.testing.util.assertThrowsError(107, attachFn);
    lf.testing.util.assertThrowsError(107, commitFn);
    lf.testing.util.assertThrowsError(107, rollbackFn);
    lf.testing.util.assertThrowsError(107, execFn);

    return whenDone;
  }).then(function() {
    asyncTestCase.continueTesting();
  }, fail);
}

/**
 * Tests that an lf.Exception.TRANSACTION is thrown when any operation is
 * attempted while a transaction is still initializing.
 */
function testThrows_StateAcquiringScope() {
  asyncTestCase.waitForAsync('testThrows_StateAcquiringScope');
  var whenDone = tx.begin([e]);
  // 107: Invalid transaction state transition: {0} -> {1}.
  lf.testing.util.assertThrowsError(107, beginFn);
  lf.testing.util.assertThrowsError(107, attachFn);
  lf.testing.util.assertThrowsError(107, commitFn);
  lf.testing.util.assertThrowsError(107, rollbackFn);
  lf.testing.util.assertThrowsError(107, execFn);

  whenDone.then(function() {
    asyncTestCase.continueTesting();
  }, fail);
}

/**
 * Tests that an lf.Exception.TRANSACTION is thrown when a set of queries that
 * will be automatically committed (no need to call commit), is in progress.
 */
function testThrows_StateExecutingAndCommitting() {
  asyncTestCase.waitForAsync('testThrows_StateExecutingAndCommitting');
  var whenDone = tx.exec([db.select().from(e)]);
  // 107: Invalid transaction state transition: {0} -> {1}.
  lf.testing.util.assertThrowsError(107, beginFn);
  lf.testing.util.assertThrowsError(107, attachFn);
  lf.testing.util.assertThrowsError(107, commitFn);
  lf.testing.util.assertThrowsError(107, rollbackFn);
  lf.testing.util.assertThrowsError(107, execFn);

  whenDone.then(function() {
    asyncTestCase.continueTesting();
  }, fail);
}

function testExec() {
  asyncTestCase.waitForAsync('testExec');
  var tx = db.createTransaction();
  var q1 = db.select(lf.fn.count(j.id).as('jid')).from(j);
  var q2 = db.select(lf.fn.count(d.id).as('did')).from(d);
  var q3 = db.delete().from(e);
  var q4 = db.delete().from(j);
  tx.exec([q1, q2, q3, q4, q1]).then(function(results) {
    assertEquals(5, results.length);
    assertEquals(sampleJobs.length, results[0][0]['jid']);
    assertEquals(sampleDepartments.length, results[1][0]['did']);
    assertEquals(0, results[4][0]['jid']);
    asyncTestCase.continueTesting();
  }, fail);
}

function testAttach_Success() {
  asyncTestCase.waitForAsync('testAttach_Success');

  var scope = [j, e];
  tx.begin(scope).then(function() {
    var q1 = db.select().from(j);
    return tx.attach(q1);
  }).then(function(results) {
    assertEquals(sampleJobs.length, results.length);

    var q2 = db.select().from(e);
    return tx.attach(q2);
  }).then(function(results) {
    assertEquals(sampleEmployees.length, results.length);

    var hireDate = dataGenerator.employeeGroundTruth.maxHireDate;
    var q3 = db.
        delete().
        from(e).
        where(e.hireDate.eq(hireDate));
    return tx.attach(q3);
  }).then(function() {
    var q4 = db.select().from(e);
    return tx.attach(q4);
  }).then(function(results) {
    assertTrue(results.length < sampleEmployees.length);
    var q5 = db.delete().from(e);
    return tx.attach(q5);
  }).then(function() {
    // Deleting all rows in the Job table.
    var q6 = db.delete().from(j);
    return tx.attach(q6);
  }).then(function() {
    var q7 = db.select().from(j);
    return tx.attach(q7);
  }).then(function(results) {
    // Expecting all rows to have been deleted within tx's context.
    assertEquals(0, results.length);

    // Expecting all job rows to *not* have been deleted from disk yet, since
    // the transaction has not been committed.
    return lf.testing.util.selectAll(global, j);
  }).then(function(results) {
    assertEquals(sampleJobs.length, results.length);

    return tx.commit();
  }).then(function() {
    // Expecting all job rows to have been deleted from disk, now that the
    // transaction was committed.
    return lf.testing.util.selectAll(global, j);
  }).then(function(results) {
    assertEquals(0, results.length);

    // Expecting all locks to have been released by previous transaction, which
    // should allow the following query to complete.
    return db.select().from(e).exec();
  }).then(function(results) {
    assertTrue(results.length < sampleEmployees.length);
    asyncTestCase.continueTesting();
  }, fail);
}

/**
 * Tests that if an attached query fails, the entire transaction is rolled back.
 */
function testAttach_Error() {
  asyncTestCase.waitForAsync('testAttach_Error');

  var scope = [j, e];
  var newJobId = 'SomeUniqueId';

  tx.begin(scope).then(function() {
    var q0 = db.select().from(j);
    return tx.attach(q0);
  }).then(function(results) {
    assertEquals(sampleJobs.length, results.length);

    // Adding a new job row.
    var newJob = j.createRow();
    newJob.setId(newJobId);
    var q1 = db.insert().into(j).values([newJob]);
    return tx.attach(q1);
  }).then(function() {
    var q2 = db.select().from(j).where(j.id.eq(newJobId));
    return tx.attach(q2);
  }).then(function(results) {
    assertEquals(1, results.length);

    var q3 = db.select().from(j);
    return tx.attach(q3);
  }).then(function(results) {
    assertEquals(sampleJobs.length + 1, results.length);

    // Attempting to add an employee row that already exists.
    var q4 = db.insert().into(e).values([sampleEmployees[0]]);
    return tx.attach(q4);
  }).thenCatch(function(e) {
    // 201: Duplicate keys are not allowed.
    assertEquals(201, e.code);

    // Checking that the transaction has been finalized.
    // 107: Invalid transaction state transition: {0} -> {1}.
    lf.testing.util.assertThrowsError(107, attachFn);
    lf.testing.util.assertThrowsError(107, commitFn);
    lf.testing.util.assertThrowsError(107, rollbackFn);
    lf.testing.util.assertThrowsError(107, beginFn);

    return lf.testing.util.selectAll(global, j);
  }).then(function(results) {
    // Checking that the entire transaction was rolled back, and therefore that
    // Job row that had been added does not appear on disk.
    assertEquals(sampleJobs.length, results.length);

    // Checking that all locks have been released, which will allow other
    // transactions referring to the same scope to execute successfully.
    return db.select().from(j).exec();
  }).then(function(results) {
    assertEquals(sampleJobs.length, results.length);
    asyncTestCase.continueTesting();
  });
}

/**
 * Tests that when a transaction is explicitly rolled back, all changes that
 * were made as part of this transaction are discarded.
 */
function testRollback() {
  asyncTestCase.waitForAsync('testRollback');

  var scope = [j, e];
  var newJobId = 'SomeUniqueId';

  tx.begin(scope).then(function() {
    // Adding a new job row.
    var newJob = j.createRow();
    newJob.setId(newJobId);
    var q1 = db.insert().into(j).values([newJob]);
    return tx.attach(q1);
  }).then(function(results) {
    var q2 = db.select().from(j).where(j.id.eq(newJobId));
    return tx.attach(q2);
  }).then(function(results) {
    assertEquals(1, results.length);

    var q3 = db.select().from(j);
    return tx.attach(q3);
  }).then(function(results) {
    assertEquals(sampleJobs.length + 1, results.length);

    return tx.rollback();
  }).then(function() {
    // Checking that the transaction has been finalized.
    // 107: Invalid transaction state transition: {0} -> {1}.
    lf.testing.util.assertThrowsError(107, attachFn);
    lf.testing.util.assertThrowsError(107, commitFn);
    lf.testing.util.assertThrowsError(107, rollbackFn);
    lf.testing.util.assertThrowsError(107, beginFn);

    return lf.testing.util.selectAll(global, j);
  }).then(function(results) {
    // Checking that the entire transaction was rolled back, and therefore that
    // Job row that had been added does not appear on disk.
    assertEquals(sampleJobs.length, results.length);

    // Expecting all locks to have been released by previous transaction, which
    // should allow the following query to complete.
    return db.select().from(j).exec();
  }).then(function() {
    asyncTestCase.continueTesting();
  });
}

/**
 * Tests the case where an attached query modifiess the results of an observed
 * query and ensures that observers are triggered.
 */
function testAttach_WithObservers() {
  asyncTestCase.waitForAsync('testAttach_WithObservers');
  var scope = [j];

  var initialJobCount = sampleJobs.length;
  var additionalJobCount = 2;

  var jobDataGenerator = new lf.testing.hrSchema.JobDataGenerator(
      hr.db.getSchema());
  var newJobs = jobDataGenerator.generate(additionalJobCount);
  newJobs.forEach(function(job, index) {
    job.setId('SomeUniqueId' + index.toString());
  });

  var observeCallback = function(changeEvents) {
    assertEquals(
        initialJobCount + additionalJobCount,
        changeEvents.length);
    assertEquals(
        initialJobCount + additionalJobCount,
        changeEvents[0]['object'].length);

    asyncTestCase.continueTesting();
  };

  var q = db.select().from(j);
  db.observe(q, observeCallback);

  tx.begin(scope).then(function() {
    // Adding a new job row.
    var q1 = db.insert().into(j).values([newJobs[0]]);
    return tx.attach(q1);
  }).then(function(results) {
    // Adding another new job row.
    var q2 = db.insert().into(j).values([newJobs[1]]);
    return tx.attach(q2);
  }).then(function() {
    return tx.commit();
  }, fail);
}
<|endoftext|>


<commit_before>'use strict'

var React = require('react')
var ReactBootrap = require('react-bootstrap')
var ReactRouterBootstrap = require('react-router-bootstrap')
var LinkContainer = ReactRouterBootstrap.LinkContainer
var Navbar = ReactBootrap.Navbar
var Nav = ReactBootrap.Nav
var NavItem = ReactBootrap.NavItem

var Header = React.createClass({
  propTypes: {
    children: React.PropTypes.object
  },
  render: function render () {
    return (

        <Navbar fluid>
          <Navbar.Header>
            <Navbar.Brand>
              <LinkContainer to={{pathname: '/'}}>
                Measure Mate
              </LinkContainer>
            </Navbar.Brand>
            <Navbar.Toggle />
          </Navbar.Header>
          <Navbar.Collapse>

              <LinkContainer to={{pathname: '/assessment/list'}}>
                <NavItem eventKey={1}>Assessments</NavItem>
              </LinkContainer>
              <LinkContainer to={{pathname: '/team/list'}}>
                <NavItem eventKey={2}>Teams</NavItem>
              </LinkContainer>

              <LinkContainer to={{pathname: '/about'}}>
                <NavItem eventKey={3}>About</NavItem>
              </LinkContainer>

          </Navbar.Collapse>
        </Navbar>

          {this.props.children}

    )
  }
})

module.exports = Header
<commit_msg>make the highlighting of active navitem work<commit_after>'use strict'

var React = require('react')
var ReactBootrap = require('react-bootstrap')
var ReactRouterBootstrap = require('react-router-bootstrap')
var LinkContainer = ReactRouterBootstrap.LinkContainer
var Navbar = ReactBootrap.Navbar
var Nav = ReactBootrap.Nav
var NavItem = ReactBootrap.NavItem

var Header = React.createClass({
  propTypes: {
    children: React.PropTypes.object
  },
  render: function render () {
    return (

        <Navbar fluid>
          <Navbar.Header>
            <Navbar.Brand>
              <LinkContainer to={{pathname: '/'}}>
                Measure Mate
              </LinkContainer>
            </Navbar.Brand>
            <Navbar.Toggle />
          </Navbar.Header>
          <Navbar.Collapse>

              <LinkContainer to={{pathname: '/assessment/'}}>
                <NavItem eventKey={1}>Assessments</NavItem>
              </LinkContainer>
              <LinkContainer to={{pathname: '/team/'}}>
                <NavItem eventKey={2}>Teams</NavItem>
              </LinkContainer>

              <LinkContainer to={{pathname: '/about'}}>
                <NavItem eventKey={3}>About</NavItem>
              </LinkContainer>

          </Navbar.Collapse>
        </Navbar>

          {this.props.children}

    )
  }
})

module.exports = Header
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { Text } from 'react-native';

import styles from '../../styles/styles';
import InPageImage from '../inPageImage';
import AnimalText from '../animalText';
import AnimalTemplate from '../animalTemplate';

const IMAGES = [
  require('../../images/animals/agamaKocincinska/01.jpg'),
  require('../../images/animals/agamaKocincinska/02.jpg'),
];

const THUMBNAILS = [
  require('../../images/animals/agamaKocincinska/01-thumb.jpg'),
  require('../../images/animals/agamaKocincinska/02-thumb.jpg'),
];

var AnimalDetail = React.createClass({
  render() {
    return (
      <AnimalTemplate firstIndex={[1]} thumbnails={THUMBNAILS} images={IMAGES} navigator={this.props.navigator}>
        <AnimalText>
          Agama kočinčinská neboli <Text style={styles.italic}>Physignathus cocincinus</Text>, pro Angličany <Text style={styles.italic}>Chineese water dragon</Text>, tedy čínský vodní drak, je plaz dlouhý kolem tří čtvrtin metru, přičemž přibližně dvě třetiny délky agamy tvoří ocas. (Je proto s podivem, že agam nejsou plné učebnice matematiky; byly by z nich krásné příklady.)
        </AnimalText>
        <AnimalText>
          Agamy kočinčinské obývají jihovýchod Asie, oblast takzvané Kočinčíny, tedy jih Vietnamu. Kromě toho je možné je potkat v Číně, Thajsku a Laosu. Žijí na místech, kde je vlhko a teplo – pro milovníky čísel to znamená až 80% vlhkost a teploty 29 ± 3 °C. V takovýchto oblastech pobývají u vody na keřích nebo malých stromech. K nebezpečí se agamy otáčejí zády – vrhají se do vody, ve které jsou jako doma, a dovedou se potápět na desítky minut.
        </AnimalText>
      <InPageImage indexes={[0]} thumbnails={THUMBNAILS} images={IMAGES} navigator={this.props.navigator} />
        <AnimalText>
          Co se potravy týče, nejčastěji si agamy pochutnávají na hmyzu. Čas od času si smlsnou i na drobných obratlovcích včetně ryb. Jen výjimečně okoštují i něco zeleného, většině agam totiž vegetariánství dvakrát nevoní. A proč by také mělo, když mají předpoklady k tomu být vynikajícími lovci – kromě plavání dokážou agamy také utíkat pouze po zadních nohou.
        </AnimalText>
        <AnimalText>
          V naší zoo žije jeden sameček a dvě samičky. Samečka lze poznat podle toho, že je barevnější, má na hřbetě větší hřeben a má žlutooranžově zbarvený spodek krku. Jinak jsou všechny agamy svrchu zelené, trochu do hněda a mají světlá bříška. (Mimochodem, hřeben mají i samičky; samečci je do něj kousají během kopulace.)
        </AnimalText>
        <AnimalText>
          Agamy jsou vejcorodé. Snůšku kladou samičky do jamky v zemi, mláďata se líhnou po dvou až dvou a půl měsících, záleží na okolní teplotě. Délka života agam je 10–15 let.
        </AnimalText>
        <AnimalText>
          A zajímavost na závěr: Agamy mají tři oči. Na temeni hlavy, mezi „normálníma“ očima, mají skvrnu, tzv. pineální oko, kterým vnímají změny intenzity světla. To jim jednak pravděpodobně pomáhá s termoregulací (slouží pro nalezení místa k vyhřívání) a jednak je chrání před nebezpečím. Spící agamy totiž tímto okem pravděpodobně dokážou poznat rozdíl v intenzitě světla, když nad nimi například letí dravec.
        </AnimalText>
      </AnimalTemplate>
    );
  }
});

module.exports = AnimalDetail;
<commit_msg>Update agamaKocincinska.adult.js<commit_after>import React, { Component } from 'react';
import { Text } from 'react-native';

import styles from '../../styles/styles';
import InPageImage from '../inPageImage';
import AnimalText from '../animalText';
import AnimalTemplate from '../animalTemplate';

const IMAGES = [
  require('../../images/animals/agamaKocincinska/01.jpg'),
  require('../../images/animals/agamaKocincinska/02.jpg'),
];

const THUMBNAILS = [
  require('../../images/animals/agamaKocincinska/01-thumb.jpg'),
  require('../../images/animals/agamaKocincinska/02-thumb.jpg'),
];

var AnimalDetail = React.createClass({
  render() {
    return (
      <AnimalTemplate firstIndex={[1]} thumbnails={THUMBNAILS} images={IMAGES} navigator={this.props.navigator}>
        <AnimalText>
          Agama kočinčinská neboli <Text style={styles.italic}>Physignathus cocincinus</Text>, pro Angličany <Text style={styles.italic}>chineese water dragon</Text>, tedy čínský vodní drak, je plaz dlouhý kolem tří čtvrtin metru, přičemž přibližně dvě třetiny délky agamy tvoří ocas. (Je proto s podivem, že agam nejsou plné učebnice matematiky; byly by z nich krásné příklady.)
        </AnimalText>
        <AnimalText>
          Agamy kočinčinské obývají jihovýchod Asie, oblast takzvané Kočinčíny, tedy jih Vietnamu. Kromě toho je možné je potkat v Číně, Thajsku a Laosu. Žijí na místech, kde je vlhko a teplo – pro milovníky čísel to znamená až 80% vlhkost a teploty 29 ± 3 °C. V takovýchto oblastech pobývají u vody na keřích nebo malých stromech. K nebezpečí se agamy otáčejí zády – vrhají se do vody, ve které jsou jako doma, a dovedou se potápět na desítky minut.
        </AnimalText>
      <InPageImage indexes={[0]} thumbnails={THUMBNAILS} images={IMAGES} navigator={this.props.navigator} />
        <AnimalText>
          Co se potravy týče, nejčastěji si agamy pochutnávají na hmyzu. Čas od času si smlsnou i na drobných obratlovcích včetně ryb. Jen výjimečně okoštují i něco zeleného, většině agam totiž vegetariánství dvakrát nevoní. A proč by také mělo, když mají předpoklady k tomu být vynikajícími lovci – kromě plavání dokážou agamy také utíkat pouze po zadních nohou.
        </AnimalText>
        <AnimalText>
          V naší zoo žije jeden sameček a dvě samičky. Samečka lze poznat podle toho, že je barevnější, má na hřbetě větší hřeben a má žlutooranžově zbarvený spodek krku. Jinak jsou všechny agamy svrchu zelené, trochu do hněda a mají světlá bříška. (Mimochodem, hřeben mají i samičky; samečci je do něj kousají během kopulace.)
        </AnimalText>
        <AnimalText>
          Agamy jsou vejcorodé. Snůšku kladou samičky do jamky v zemi, mláďata se líhnou po dvou až dvou a půl měsících, záleží na okolní teplotě. Délka života agam je 10–15 let.
        </AnimalText>
        <AnimalText>
          A zajímavost na závěr: Agamy mají tři oči. Na temeni hlavy, mezi „normálníma“ očima, mají skvrnu, tzv. pineální oko, kterým vnímají změny intenzity světla. To jim jednak pravděpodobně pomáhá s termoregulací (slouží pro nalezení místa k vyhřívání) a jednak je chrání před nebezpečím. Spící agamy totiž tímto okem pravděpodobně dokážou poznat rozdíl v intenzitě světla, když nad nimi například letí dravec.
        </AnimalText>
      </AnimalTemplate>
    );
  }
});

module.exports = AnimalDetail;
<|endoftext|>


<commit_before>export class NavigationDuplicated extends Error {
  constructor () {
    super('Navigating to current location is not allowed')
    this.name = this._name = 'NavigationDuplicated'
  }
}

// support IE9
NavigationDuplicated._name = 'NavigationDuplicated'
<commit_msg>feat(errors): add stack trace to NavigationDuplicated<commit_after>export class NavigationDuplicated extends Error {
  constructor (normalizedLocation) {
    super()
    this.name = this._name = 'NavigationDuplicated'
    // passing the message to super() doesn't seem to work in the transpiled version
    this.message = `Navigating to current location ("${
      normalizedLocation.fullPath
    }") is not allowed`
    // add a stack property so services like Sentry can correctly display it
    Object.defineProperty(this, 'stack', {
      value: new Error().stack,
      writable: true,
      configurable: true
    })
    // we could also have used
    // Error.captureStackTrace(this, this.constructor)
    // but it only exists on node and chrome
  }
}

// support IE9
NavigationDuplicated._name = 'NavigationDuplicated'
<|endoftext|>


<commit_before>/* global goog, obacht */

goog.provide('obacht.themes');

/**
 * Obacht Themes Data
 */
obacht.themes = {
    'water': {
        world: {
            files: {
                ground: 'assets/themes/water/ground.png',
                landscapeA: 'assets/themes/water/landscapeA.png',
                landscapeB: 'assets/themes/water/landscapeB.png',
                clouds: 'assets/themes/water/clouds.png',
                sky: 'assets/themes/water/sky.jpg'
            }
        },
        traps: {
            //Krebs
            crab: {
                file: 'assets/themes/water/traps/crab.png',
                position: 'ground',
                width: 150,
                height: 91,
                boundingBoxes: [
                    {x: 1, y: 10, width: 26, height: 31},
                    {x: 21, y: 42, width: 26, height: 46},
                    {x: 47, y: 24, width: 63, height: 55},
                    {x: 110, y: 43, width: 28, height: 46},
                    {x: 123, y: 2, width: 26, height: 41}
                ]
            },

            //Anker
            anchor: {
                file: 'assets/themes/water/traps/anchor.png',
                position: 'ground',
                width: 110,
                height: 120,
                boundingBoxes: [
                    {x: 0, y: 27, width: 29, height: 78},
                    {x: 72, y: 0, width: 30, height: 32},
                    {x: 49, y: 32, width: 32, height: 30},
                    {x: 35, y: 62, width: 28, height: 18},
                    {x: 29, y: 80, width: 79, height: 38}

                ]
            },

            //Qualle
            jellyfish: {
                file: 'assets/themes/water/traps/jellyfish.png',
                position: 'ground',
                width: 120,
                height: 140,
                boundingBoxes: [
                    {x: 1, y: 1, width: 99, height: 129},
                    {x: 100, y: 60, width: 18, height: 51}

                ]
            },

            //Seeigel
            seaurchin: {
                file: 'assets/themes/water/traps/seaurchin.png',
                position: 'ground',
                width: 150,
                height: 115,
                boundingBoxes: [
                    {x: 3, y: 18, width: 56, height: 56},
                    {x: 13, y: 75, width: 45, height: 21},
                    {x: 58, y: 5, width: 59, height: 100},
                    {x: 117, y: 26, width: 29, height: 66}

                ]
            },

            //Hai
            shark: {
                file: 'assets/themes/water/traps/shark.png',
                position: 'air',
                width: 150,
                height: 73,
                boundingBoxes: [
                    {x: 1, y: 12, width: 64, height: 22},
                    {x: 9, y: 34, width: 56, height: 22},
                    {x: 39, y: 56, width: 27, height: 15},
                    {x: 65, y: 2, width: 26, height: 62},
                    {x: 91, y: 22, width: 27, height: 36},
                    {x: 119, y: 7, width: 22, height: 46}

                ]
            },

            //Schildkröte
            turtle: {
                file: 'assets/themes/water/traps/turtle.png',
                position: 'air',
                width: 150,
                height: 73,
                boundingBoxes: [
                    {x: 1, y: 2, width: 30, height: 18},
                    {x: 13, y: 20, width: 18, height: 36},
                    {x: 19, y: 56, width: 27, height: 14},
                    {x: 31, y: 6, width: 73, height: 37},
                    {x: 104, y: 28, width: 44, height: 13},
                    {x: 46, y: 43, width: 10, height: 12},
                    {x: 56, y: 43, width: 10, height: 20},
                    {x: 66, y: 56, width: 19, height: 14}

                ]
            },

            //Clownfisch
            clownfish: {
                file: 'assets/themes/water/traps/clownfish.png',
                position: 'air',
                width: 150,
                height: 82,
                boundingBoxes: [
                    {x: 75, y: 41, width: 150, height: 82},
                    {x: 18, y: 19, width: 15, height: 47},
                    {x: 33, y: 3, width: 39, height: 65},
                    {x: 44, y: 68, width: 28, height: 12},
                    {x: 72, y: 11, width: 44, height: 63},
                    {x: 116, y: 35, width: 32, height: 29}

                ]
            }
        },
        boni: {
            kaktus: {
                file: '../KaktusBonus.png' //sample value
            }
        }
    },
    'desert': {
        world: {
            files: {
                ground: 'assets/themes/desert/ground.png',
                landscapeA: 'assets/themes/desert/landscapeA.png',
                landscapeB: 'assets/themes/desert/landscapeB.png',
                clouds: 'assets/themes/desert/clouds.png',
                sky: 'assets/themes/desert/sky.jpg'
            }
        },
        traps: {
            //Skorpion
            scorpion: {
                file: 'assets/themes/desert/traps/scorpion.png',
                position: 'ground',
                width: 150,
                height: 119,
                boundingBoxes: [
                    {x: 83, y: 0, width: 66, height: 55},
                    {x: 3, y: 55, width: 80, height: 60}
                ]
            },

            //Schädel
            skull: {
                file: 'assets/themes/desert/traps/skull.png',
                position: 'ground',
                width: 140,
                height: 120,
                boundingBoxes: [
                    {x: 75, y: 0, width: 35, height: 64},
                    {x: 56, y: 50, width: 18, height: 29},
                    {x: 34, y: 65, width: 22, height: 14},
                    {x: 3, y: 79, width: 53, height: 40}
                ]
            },

            //Geier
            vulture: {
                file: 'assets/themes/desert/traps/vulture.png',
                position: 'air',
                width: 170,
                height: 90,
                boundingBoxes: [
                    {x: 2, y: 14, width: 34, height: 32},
                    {x: 36, y: 42, width: 37, height: 7},
                    {x: 73, y: 2, width: 67, height: 58},
                    {x: 96, y: 60, width: 42, height: 10},
                    {x: 138, y: 67, width: 31, height: 23}
                ]
            },

            //Kaktus
            cactus: {
                file: 'assets/themes/desert/traps/cactus.png',
                position: 'air',
                width: 100,
                height: 160,
                boundingBoxes: [
                    {x: 4, y: 15, width: 57, height: 85},
                    {x: 26, y: 100, width: 31, height: 58}
                ]
            },

            //Schlange
            snake: {
                file: 'assets/themes/desert/traps/snake.png',
                position: 'ground',
                width: 98,
                height: 100,
                boundingBoxes: [
                    {x: 36, y: 0, width: 32, height: 9},
                    {x: 47, y: 9, width: 20, height: 30},
                    {x: 39, y: 39, width: 15, height: 20},
                    {x: 33, y: 59, width: 14, height: 19},
                    {x: 1, y: 78, width: 31, height: 20}
                ]
            },

            //Falke
            hawk: {
                file: 'assets/themes/desert/traps/hawk.png',
                position: 'air',
                width: 110,
                height: 104,
                boundingBoxes: [
                    {x: 52, y: 4, width: 25, height: 15},
                    {x: 34, y: 19, width: 25, height: 18},
                    {x: 26, y: 37, width: 25, height: 20},
                    {x: 1, y: 57, width: 25, height: 17},
                    {x: 26, y: 69, width: 27, height: 11},
                    {x: 53, y: 74, width: 31, height: 10},
                    {x: 84, y: 83, width: 25, height: 8},
                    {x: 34, y: 81, width: 10, height: 21}

                ]
            }
        },
        boni: {
            kaktus: {
                file: '../KaktusBonus.png' //sample value
            }
        }
    },
    'meadow': {
        world: {
            files: {
                ground: 'assets/themes/meadow/ground.png',
                landscapeA: 'assets/themes/meadow/landscapeA.png',
                landscapeB: 'assets/themes/meadow/landscapeB.png',
                clouds: 'assets/themes/meadow/clouds.png',
                sky: 'assets/themes/meadow/sky.jpg'
            }
        },
        traps: {
            //Biene
            bee: {
                file: 'assets/themes/meadow/traps/bee.png',
                position: 'air',
                width: 0,
                height: 0,
                boundingBoxes: [
                    {x: 0, y: 0, width: 0, height: 0},
                    {x: 0, y: 0, width: 0, height: 0}
                ]
            },

            //Schnecke
            snail: {
                file: 'assets/themes/meadow/traps/snail.png',
                position: 'ground',
                width: 140,
                height: 116,
                boundingBoxes: [
                    {x: 3, y: 51, width: 12, height: 16},
                    {x: 2, y: 67, width: 29, height: 32},
                    {x: 18, y: 48, width: 4, height: 19},
                    {x: 31, y: 20, width: 15, height: 65},
                    {x: 46, y: 10, width: 24, height: 75},
                    {x: 70, y: 2, width: 35, height: 83},
                    {x: 105, y: 10, width: 21, height: 75},
                    {x: 126, y: 27, width: 12, height: 58},
                    {x: 31, y: 85, width: 98, height: 29}
                ]
            },

            //Marienkäfer
            beetle: {
                file: 'assets/themes/meadow/traps/beetle.png',
                position: 'air',
                width: 0,
                height: 0,
                boundingBoxes: [
                    {x: 0, y: 0, width: 0, height: 0},
                    {x: 0, y: 0, width: 0, height: 0}
                ]
            },

            //Baumstumpf
            treestump: {
                file: 'assets/themes/meadow/traps/treestump.png',
                position: 'ground',
                width: 120,
                height: 129,
                boundingBoxes: [
                    {x: 14, y: 0, width: 95, height: 89},
                    {x: 7, y: 89, width: 106, height: 33}
                ]
            },

            //Igel
            hedgehog: {
                file: 'assets/themes/meadow/traps/hedgehog.png',
                position: 'ground',
                width: 150,
                height: 87,
                boundingBoxes: [
                    {x: 1, y: 46, width: 10, height: 9},
                    {x: 11, y: 44, width: 11, height: 22},
                    {x: 22, y: 37, width: 14, height: 33},
                    {x: 36, y: 20, width: 103, height: 58},
                    {x: 53, y: 10, width: 78, height: 10},
                    {x: 72, y: 2, width: 48, height: 8},
                    {x: 139, y: 29, width: 9, height: 39},
                    {x: 65, y: 78, width: 62, height: 8}
                ]
            },

            //Pilz
            mushroom: {
                file: 'assets/themes/meadow/traps/mushroom.png',
                position: 'ground',
                width: 130,
                height: 146,
                boundingBoxes: [
                    {x: 43, y: 1, width: 56, height: 9},
                    {x: 23, y: 10, width: 93, height: 12},
                    {x: 10, y: 22, width: 117, height: 16},
                    {x: 104, y: 38, width: 24, height: 23},
                    {x: 40, y: 77, width: 64, height: 59}

                ]
            },

            //Vogelscheuche
            scarecrow: {
                file: 'assets/themes/meadow/traps/scarecrow.png',
                position: 'ground',
                width: 100,
                height: 160,
                boundingBoxes: [
                    {x: 30, y: 1, width: 31, height: 15},
                    {x: 24, y: 16, width: 56, height: 26},
                    {x: 28, y: 42, width: 43, height: 32},
                    {x: 2, y: 74, width: 96, height: 14},
                    {x: 35, y: 88, width: 33, height: 47},
                    {x: 44, y: 134, width: 13, height: 24}

                ]
            }

        },
        boni: {

        }

    }
};
<commit_msg>adjust bounding boxes<commit_after>/* global goog, obacht */

goog.provide('obacht.themes');

/**
 * Obacht Themes Data
 */
obacht.themes = {
    'water': {
        world: {
            files: {
                ground: 'assets/themes/water/ground.png',
                landscapeA: 'assets/themes/water/landscapeA.png',
                landscapeB: 'assets/themes/water/landscapeB.png',
                clouds: 'assets/themes/water/clouds.png',
                sky: 'assets/themes/water/sky.jpg'
            }
        },
        traps: {
            //Krebs
            crab: {
                file: 'assets/themes/water/traps/crab.png',
                position: 'ground',
                width: 150,
                height: 91,
                boundingBoxes: [
                    {x: 1, y: 10, width: 26, height: 29},
                    {x: 21, y: 25, width: 117, height: 54}
                ]
            },

            //Anker
            anchor: {
                file: 'assets/themes/water/traps/anchor.png',
                position: 'ground',
                width: 110,
                height: 120,
                boundingBoxes: [
                    {x: 0, y: 27, width: 29, height: 78},
                    {x: 49, y: 2, width: 51, height: 78}

                ]
            },

            //Qualle
            jellyfish: {
                file: 'assets/themes/water/traps/jellyfish.png',
                position: 'ground',
                width: 120,
                height: 140,
                boundingBoxes: [
                    {x: 1, y: 1, width: 99, height: 129},
                    {x: 100, y: 60, width: 18, height: 51}

                ]
            },

            //Seeigel
            seaurchin: {
                file: 'assets/themes/water/traps/seaurchin.png',
                position: 'ground',
                width: 150,
                height: 115,
                boundingBoxes: [
                    {x: 5, y: 5, width: 112, height: 100},
                    {x: 117, y: 26, width: 29, height: 66}

                ]
            },

            //Hai
            shark: {
                file: 'assets/themes/water/traps/shark.png',
                position: 'air',
                width: 150,
                height: 73,
                boundingBoxes: [
                    {x: 2, y: 12, width: 37, height: 47},
                    {x: 0, y: 0, width: 0, height: 0}

                ]
            },

            //Schildkröte
            turtle: {
                file: 'assets/themes/water/traps/turtle.png',
                position: 'air',
                width: 150,
                height: 73,
                boundingBoxes: [
                    {x: 2, y: 6, width: 102, height: 37},
                    {x: 104, y: 28, width: 44, height: 13},
                    {x: 14, y: 43, width: 71, height: 26}

                ]
            },

            //Clownfisch
            clownfish: {
                file: 'assets/themes/water/traps/clownfish.png',
                position: 'air',
                width: 150,
                height: 82,
                boundingBoxes: [
                    {x: 3, y: 3, width: 113, height: 76},
                    {x: 116, y: 35, width: 32, height: 29}

                ]
            }
        },
        boni: {
            kaktus: {
                file: '../KaktusBonus.png' //sample value
            }
        }
    },
    'desert': {
        world: {
            files: {
                ground: 'assets/themes/desert/ground.png',
                landscapeA: 'assets/themes/desert/landscapeA.png',
                landscapeB: 'assets/themes/desert/landscapeB.png',
                clouds: 'assets/themes/desert/clouds.png',
                sky: 'assets/themes/desert/sky.jpg'
            }
        },
        traps: {
            //Skorpion
            scorpion: {
                file: 'assets/themes/desert/traps/scorpion.png',
                position: 'ground',
                width: 150,
                height: 119,
                boundingBoxes: [
                    {x: 3, y: 55, width: 80, height: 60},
                    {x: 83, y: 2, width: 66, height: 83}
                ]
            },

            //Schädel
            skull: {
                file: 'assets/themes/desert/traps/skull.png',
                position: 'ground',
                width: 140,
                height: 120,
                boundingBoxes: [
                    {x: 75, y: 1, width: 14, height: 50},
                    {x: 3, y: 50, width: 105, height: 59},
                    {x: 108, y: 75, width: 29, height: 13}
                ]
            },

            //Geier
            vulture: {
                file: 'assets/themes/desert/traps/vulture.png',
                position: 'air',
                width: 170,
                height: 90,
                boundingBoxes: [
                    {x: 1, y: 14, width: 64, height: 33},
                    {x: 65, y: 1, width: 76, height: 67},
                    {x: 129, y: 68, width: 39, height: 19}
                ]
            },

            //Kaktus
            cactus: {
                file: 'assets/themes/desert/traps/cactus.png',
                position: 'air',
                width: 100,
                height: 160,
                boundingBoxes: [
                    {x: 4, y: 15, width: 57, height: 85},
                    {x: 26, y: 100, width: 31, height: 58}
                ]
            },

            //Schlange
            snake: {
                file: 'assets/themes/desert/traps/snake.png',
                position: 'ground',
                width: 98,
                height: 100,
                boundingBoxes: [
                    {x: 36, y: 1, width: 32, height: 78},
                    {x: 2, y: 78, width: 94, height: 20},
                    {x: 68, y: 66, width: 27, height: 12}
                ]
            },

            //Falke
            hawk: {
                file: 'assets/themes/desert/traps/hawk.png',
                position: 'air',
                width: 110,
                height: 104,
                boundingBoxes: [
                    {x: 3, y: 4, width: 74, height: 79},
                    {x: 77, y: 77, width: 31, height: 13},
                    {x: 34, y: 83, width: 13, height: 19}

                ]
            }
        },
        boni: {
            kaktus: {
                file: '../KaktusBonus.png' //sample value
            }
        }
    },
    'meadow': {
        world: {
            files: {
                ground: 'assets/themes/meadow/ground.png',
                landscapeA: 'assets/themes/meadow/landscapeA.png',
                landscapeB: 'assets/themes/meadow/landscapeB.png',
                clouds: 'assets/themes/meadow/clouds.png',
                sky: 'assets/themes/meadow/sky.jpg'
            }
        },
        traps: {
            //Biene
            bee: {
                file: 'assets/themes/meadow/traps/bee.png',
                position: 'air',
                width: 0,
                height: 0,
                boundingBoxes: [
                    {x: 0, y: 0, width: 0, height: 0}
                ]
            },

            //Schnecke
            snail: {
                file: 'assets/themes/meadow/traps/snail.png',
                position: 'ground',
                width: 140,
                height: 116,
                boundingBoxes: [
                    {x: 2, y: 50, width: 29, height: 49},
                    {x: 31, y: 3, width: 107, height: 82}
                ]
            },

            //Marienkäfer
            beetle: {
                file: 'assets/themes/meadow/traps/beetle.png',
                position: 'air',
                width: 0,
                height: 0,
                boundingBoxes: [
                    {x: 0, y: 0, width: 0, height: 0}
                ]
            },

            //Baumstumpf
            treestump: {
                file: 'assets/themes/meadow/traps/treestump.png',
                position: 'ground',
                width: 120,
                height: 129,
                boundingBoxes: [
                    {x: 14, y: 0, width: 95, height: 89},
                    {x: 7, y: 89, width: 106, height: 33}
                ]
            },

            //Igel
            hedgehog: {
                file: 'assets/themes/meadow/traps/hedgehog.png',
                position: 'ground',
                width: 150,
                height: 87,
                boundingBoxes: [
                    {x: 1, y: 46, width: 24, height: 19},
                    {x: 25, y: 7, width: 119, height: 71}
                ]
            },

            //Pilz
            mushroom: {
                file: 'assets/themes/meadow/traps/mushroom.png',
                position: 'ground',
                width: 130,
                height: 146,
                boundingBoxes: [
                    {x: 3, y: 2, width: 125, height: 67},
                    {x: 40, y: 69, width: 64, height: 67}

                ]
            },

            //Vogelscheuche
            scarecrow: {
                file: 'assets/themes/meadow/traps/scarecrow.png',
                position: 'ground',
                width: 100,
                height: 160,
                boundingBoxes: [
                    {x: 25, y: 2, width: 54, height: 72},
                    {x: 2, y: 74, width: 96, height: 14},
                    {x: 35, y: 88, width: 33, height: 68}
                ]
            }

        },
        boni: {

        }

    }
};
<|endoftext|>


<commit_before>/**
 * Copyright 2015-present Tuan Le.
 *
 * Licensed under the MIT License.
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://opensource.org/licenses/mit-license.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *------------------------------------------------------------------------
 *
 * @module Hyperflow (Hflow) (A toolkit & library for developing universal app)
 * @description - Hflow namespace setup. Initialize Hflow, adding core modules, and apply settings.
 *
 * @author Tuan Le (tuan.t.lei@gmail.com)
 */
/* @flow */
'use strict'; // eslint-disable-line

/* load CommonElement */
import CommonElement from './core/elements/common-element';

/* load DataElement */
import DataElement from './core/elements/data-element';

/* load CompositeElement */
import CompositeElement from './core/elements/composite-element';

/* load Composer */
import Composer from './core/composer';

/* load StoreFactory */
import StoreFactory from './core/factories/store-factory';

/* load DomainFactory */
import DomainFactory from './core/factories/domain-factory';

/* load InterfaceFactory */
import InterfaceFactory from './core/factories/interface-factory';

/* load ServiceFactory */
import ServiceFactory from './core/factories/service-factory';

/* load AppFactory */
import AppFactory from './core/factories/app-factory';

/* load test AgentFactory */
import AgentFactory from './core/factories/agent-factory';

/* load test FixtureFactory and composites */
// import FixtureFactory from './core/factories/fixture-factory';
// import DomainTestFixtureComposite from './core/factories/composites/test-fixtures/domain-test-fixture-composite';
// import ServiceTestFixtureComposite from './core/factories/composites/test-fixtures/service-test-fixture-composite';
// import StoreTestFixtureComposite from './core/factories/composites/test-fixtures/store-test-fixture-composite';
// import InterfaceTestFixtureComposite from './core/factories/composites/test-fixtures/interface-test-fixture-composite';

/* load test runner composites library */
// import TapeTestRunnerComposite from './core/factories/composites/tape-test-runner-composite';

/* load state composites library */
import StateReducerComposite from './core/factories/composites/state-reducer-composite';
import StateTimeTraversalComposite from './core/factories/composites/state-time-traversal-composite';

/* load React composites library */
import ReactComponentComposite from './composites/interfaces/react-component-composite';
import ReactClientNativeAppComponentComposite from './composites/apps/client-native/react-app-component-composite';
import ReactClientWebAppComponentComposite from './composites/apps/client-web/react-app-component-composite';
import ReactServerAppComponentComposite from './composites/apps/server/react-app-component-composite';
import ReactClientWebAppRendererComposite from './composites/apps/client-web/react-app-renderer-composite';
import ReactClientNativeAppRendererComposite from './composites/apps/client-native/react-app-renderer-composite';
import ReactServerAppRendererComposite from './composites/apps/server/react-app-renderer-composite';

/* load service library */
import WebStorageComposite from './composites/services/client-web/web-storage-composite';
import ASyncStorageComposite from './composites/services/client-native/async-storage-composite';
import PGComposite from './composites/services/server/pg-composite';

let Hflow = null;

/**
 * @description - Setup and initialize modules & dependencies for Hflow`s namespaces.
 *
 * @function init
 * @param {object} setting - Hflow's global settings.
 * @returns {object}
 */
const init = function init ({
    TARGET = `client-web`,
    DEVELOPMENT = true,
    ENABLE_INFO_MESSAGE = true,
    ENABLE_WARN_LVL0_MESSAGE = false,
    ENABLE_WARN_LVL1_MESSAGE = true
} = {}) {
    if (Hflow === null) {
        const common = CommonElement({
            devleopment: DEVELOPMENT,
            enableInfoMessage: ENABLE_INFO_MESSAGE,
            enableWarn0Message: ENABLE_WARN_LVL0_MESSAGE,
            enableWarn1Message: ENABLE_WARN_LVL1_MESSAGE
        });
        const HflowProperty = {
            VERSION: `0.1.0-beta8`,
            ENV: TARGET === `server` ? process.env : {}, // eslint-disable-line
            TARGET,
            DEVELOPMENT,
            /* set composer factory namespace */
            Composer,
            /* set data and composite element namespaces */
            Data: DataElement,
            Composite: CompositeElement,
            /* set factory event stream Ids creator */
            Event: {
                /**
                 * @description - Function to contruct an event Id structure for factory event stream.
                 *
                 * @function eventIdCreate
                 * @param {object} eventIdObj - Event Id contructor object
                 * @returns {object}
                 */
                create: function create (sourceEventMap) {
                    if (!common.isSchema({
                        asEvents: `array|undefined`,
                        onEvents: `array|undefined`,
                        doEvents: `array|undefined`,
                        requestEvents: `array|undefined`,
                        broadcastEvents: `array|undefined`
                    }).of(sourceEventMap)) {
                        common.log(`error`, `Event.create - Input event map is invalid.`);
                    } else {
                        /* helper function to convert dash to uppercase underscore */
                        const dashToUpperCaseUnderscore = function dashToUpperCaseUnderscore (str) {
                            return str.replace(/-([a-z])/g, (match, word) => {
                                return `_${word}`;
                            }).toUpperCase();
                        };

                        const outputEventMap = Object.keys(sourceEventMap).reduce((_outputEventMap, key) => {
                            if (key === `asEvents`) {
                                if (sourceEventMap[key].every((_key) => common.isString(_key))) {
                                    _outputEventMap[`AS`] = sourceEventMap[key].reduce((asEventMap, _key) => {
                                        asEventMap[
                                            dashToUpperCaseUnderscore(_key)
                                        ] = `as-${_key}`;
                                        return asEventMap;
                                    }, {});
                                } else {
                                    common.log(`error`, `Event.create - Input 'as' event keys are invalid.`);
                                }
                            }
                            if (key === `onEvents`) {
                                if (sourceEventMap[key].every((_key) => common.isString(_key))) {
                                    _outputEventMap[`ON`] = sourceEventMap[key].reduce((onEventMap, _key) => {
                                        onEventMap[
                                            dashToUpperCaseUnderscore(_key)
                                        ] = `on-${_key}`;
                                        return onEventMap;
                                    }, {});
                                } else {
                                    common.log(`error`, `Event.create - Input 'on' event keys are invalid.`);
                                }
                            }
                            if (key === `doEvents`) {
                                if (sourceEventMap[key].every((_key) => common.isString(_key))) {
                                    _outputEventMap[`DO`] = sourceEventMap[key].reduce((doEventMap, _key) => {
                                        doEventMap[
                                            dashToUpperCaseUnderscore(_key)
                                        ] = `do-${_key}`;
                                        return doEventMap;
                                    }, {});
                                } else {
                                    common.log(`error`, `Event.create - Input 'do' event keys are invalid.`);
                                }
                            }
                            if (key === `broadcastEvents`) {
                                if (sourceEventMap[key].every((_key) => common.isString(_key))) {
                                    _outputEventMap[`BROADCAST`] = sourceEventMap[key].reduce((broadcastEventMap, _key) => {
                                        broadcastEventMap[
                                            dashToUpperCaseUnderscore(_key)
                                        ] = `broadcast-${_key}`;
                                        return broadcastEventMap;
                                    }, {});
                                } else {
                                    common.log(`error`, `Event.create - Input 'broadcast' event keys are invalid.`);
                                }
                            }
                            if (key === `requestEvents`) {
                                if (sourceEventMap[key].every((_key) => common.isString(_key))) {
                                    _outputEventMap[`REQUEST`] = sourceEventMap[key].reduce((requestForEventMap, _key) => {
                                        requestForEventMap[
                                            dashToUpperCaseUnderscore(_key)
                                        ] = `request-for-${_key}`;
                                        return requestForEventMap;
                                    }, {});
                                    _outputEventMap[`RESPONSE`] = {
                                        WITH: sourceEventMap[key].reduce((responseToEventMap, _key) => {
                                            responseToEventMap[
                                                dashToUpperCaseUnderscore(_key)
                                            ] = `response-with-${_key}`;
                                            return responseToEventMap;
                                        }, {}),
                                        TO: sourceEventMap[key].reduce((responseToEventMap, _key) => {
                                            responseToEventMap[
                                                dashToUpperCaseUnderscore(_key)
                                            ] = {
                                                OK: `response-to-${_key}-ok`,
                                                ERROR: `response-to-${_key}-error`,
                                                UNAUTHORIZED: `response-to-${_key}-unauthorized`,
                                                NOT_FOUND: `response-to-${_key}-not-found`,
                                                CONFLICT: `response-to-${_key}-conflict`
                                            };
                                            return responseToEventMap;
                                        }, {})
                                    };
                                } else {
                                    common.log(`error`, `Event.create - Input 'request-for' event keys are invalid.`);
                                }
                            }
                            return _outputEventMap;
                        }, {});
                        // return Object.freeze(outputEventMap);
                        return outputEventMap;
                    }
                }
            },
            /* set store, interface, domain, and service factory namespaces */
            Domain: DomainFactory,
            Store: StoreFactory,
            Interface: InterfaceFactory,
            Service: ServiceFactory,
            /* set app factory namespace */
            App: AppFactory,
            /* set test agent & fixtures factory namespace */
            Agent: AgentFactory,
            // Fixture: FixtureFactory,
            /* set state composite factory namespace */
            State: {
                ReducerComposite: StateReducerComposite,
                TimeTraversalComposite: StateTimeTraversalComposite
            },
            /* set test fixtures composites namespace */
            // Test: {
            //     TapeRunnerComposite: TapeTestRunnerComposite,
            //     DomainFixtureComposite: DomainTestFixtureComposite,
            //     StoreFixtureComposite: StoreTestFixtureComposite,
            //     InterfaceFixtureComposite: InterfaceTestFixtureComposite,
            //     ServiceFixtureComposite: ServiceTestFixtureComposite
            // },
            /* set composite library namespace */
            React: {
                ComponentComposite: ReactComponentComposite,
                AppComponentComposite: (() => {
                    switch (TARGET) { // eslint-disable-line
                    case `client-native`:
                        return ReactClientNativeAppComponentComposite;
                    case `client-web`:
                        return ReactClientWebAppComponentComposite;
                    case `server`:
                        return ReactServerAppComponentComposite;
                    }
                })(),
                AppRendererComposite: (() => {
                    switch (TARGET) { // eslint-disable-line
                    case `client-native`:
                        return ReactClientNativeAppRendererComposite;
                    case `client-web`:
                        return ReactClientWebAppRendererComposite;
                    case `server`:
                        return ReactServerAppRendererComposite;
                    }
                })()
            },
            Storage: (() => {
                switch (TARGET) { // eslint-disable-line
                case `client-native`:
                    return {
                        ASyncStorageComposite
                    };
                case `client-web`:
                    return {
                        WebStorageComposite
                    };
                case `server`:
                    return {
                        PGComposite
                    };
                }
            })()
        };

        /* create an initialized Hflow object */
        Hflow = Object.freeze(common.mix(common, {
            exclusion: {
                /* hide reveal method, reveal is for internal use only */
                keys: [
                    `reveal`
                ]
            }
        }).with(HflowProperty));
    }
    return Hflow;
};

export {
    Hflow,
    init
};
<commit_msg>Added NOT_MODIFIED response in Hflow.Event.create method. Bumped to 0.1.0-beta9 version.<commit_after>/**
 * Copyright 2015-present Tuan Le.
 *
 * Licensed under the MIT License.
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://opensource.org/licenses/mit-license.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *------------------------------------------------------------------------
 *
 * @module Hyperflow (Hflow) (A toolkit & library for developing universal app)
 * @description - Hflow namespace setup. Initialize Hflow, adding core modules, and apply settings.
 *
 * @author Tuan Le (tuan.t.lei@gmail.com)
 */
/* @flow */
'use strict'; // eslint-disable-line

/* load CommonElement */
import CommonElement from './core/elements/common-element';

/* load DataElement */
import DataElement from './core/elements/data-element';

/* load CompositeElement */
import CompositeElement from './core/elements/composite-element';

/* load Composer */
import Composer from './core/composer';

/* load StoreFactory */
import StoreFactory from './core/factories/store-factory';

/* load DomainFactory */
import DomainFactory from './core/factories/domain-factory';

/* load InterfaceFactory */
import InterfaceFactory from './core/factories/interface-factory';

/* load ServiceFactory */
import ServiceFactory from './core/factories/service-factory';

/* load AppFactory */
import AppFactory from './core/factories/app-factory';

/* load test AgentFactory */
import AgentFactory from './core/factories/agent-factory';

/* load test FixtureFactory and composites */
// import FixtureFactory from './core/factories/fixture-factory';
// import DomainTestFixtureComposite from './core/factories/composites/test-fixtures/domain-test-fixture-composite';
// import ServiceTestFixtureComposite from './core/factories/composites/test-fixtures/service-test-fixture-composite';
// import StoreTestFixtureComposite from './core/factories/composites/test-fixtures/store-test-fixture-composite';
// import InterfaceTestFixtureComposite from './core/factories/composites/test-fixtures/interface-test-fixture-composite';

/* load test runner composites library */
// import TapeTestRunnerComposite from './core/factories/composites/tape-test-runner-composite';

/* load state composites library */
import StateReducerComposite from './core/factories/composites/state-reducer-composite';
import StateTimeTraversalComposite from './core/factories/composites/state-time-traversal-composite';

/* load React composites library */
import ReactComponentComposite from './composites/interfaces/react-component-composite';
import ReactClientNativeAppComponentComposite from './composites/apps/client-native/react-app-component-composite';
import ReactClientWebAppComponentComposite from './composites/apps/client-web/react-app-component-composite';
import ReactServerAppComponentComposite from './composites/apps/server/react-app-component-composite';
import ReactClientWebAppRendererComposite from './composites/apps/client-web/react-app-renderer-composite';
import ReactClientNativeAppRendererComposite from './composites/apps/client-native/react-app-renderer-composite';
import ReactServerAppRendererComposite from './composites/apps/server/react-app-renderer-composite';

/* load service library */
import WebStorageComposite from './composites/services/client-web/web-storage-composite';
import ASyncStorageComposite from './composites/services/client-native/async-storage-composite';
import PGComposite from './composites/services/server/pg-composite';

let Hflow = null;

/**
 * @description - Setup and initialize modules & dependencies for Hflow`s namespaces.
 *
 * @function init
 * @param {object} setting - Hflow's global settings.
 * @returns {object}
 */
const init = function init ({
    TARGET = `client-web`,
    DEVELOPMENT = true,
    ENABLE_INFO_MESSAGE = true,
    ENABLE_WARN_LVL0_MESSAGE = false,
    ENABLE_WARN_LVL1_MESSAGE = true
} = {}) {
    if (Hflow === null) {
        const common = CommonElement({
            devleopment: DEVELOPMENT,
            enableInfoMessage: ENABLE_INFO_MESSAGE,
            enableWarn0Message: ENABLE_WARN_LVL0_MESSAGE,
            enableWarn1Message: ENABLE_WARN_LVL1_MESSAGE
        });
        const HflowProperty = {
            VERSION: `0.1.0-beta9`,
            ENV: TARGET === `server` ? process.env : {}, // eslint-disable-line
            TARGET,
            DEVELOPMENT,
            /* set composer factory namespace */
            Composer,
            /* set data and composite element namespaces */
            Data: DataElement,
            Composite: CompositeElement,
            /* set factory event stream Ids creator */
            Event: {
                /**
                 * @description - Function to contruct an event Id structure for factory event stream.
                 *
                 * @function eventIdCreate
                 * @param {object} eventIdObj - Event Id contructor object
                 * @returns {object}
                 */
                create: function create (sourceEventMap) {
                    if (!common.isSchema({
                        asEvents: `array|undefined`,
                        onEvents: `array|undefined`,
                        doEvents: `array|undefined`,
                        requestEvents: `array|undefined`,
                        broadcastEvents: `array|undefined`
                    }).of(sourceEventMap)) {
                        common.log(`error`, `Event.create - Input event map is invalid.`);
                    } else {
                        /* helper function to convert dash to uppercase underscore */
                        const dashToUpperCaseUnderscore = function dashToUpperCaseUnderscore (str) {
                            return str.replace(/-([a-z])/g, (match, word) => {
                                return `_${word}`;
                            }).toUpperCase();
                        };

                        const outputEventMap = Object.keys(sourceEventMap).reduce((_outputEventMap, key) => {
                            if (key === `asEvents`) {
                                if (sourceEventMap[key].every((_key) => common.isString(_key))) {
                                    _outputEventMap[`AS`] = sourceEventMap[key].reduce((asEventMap, _key) => {
                                        asEventMap[
                                            dashToUpperCaseUnderscore(_key)
                                        ] = `as-${_key}`;
                                        return asEventMap;
                                    }, {});
                                } else {
                                    common.log(`error`, `Event.create - Input 'as' event keys are invalid.`);
                                }
                            }
                            if (key === `onEvents`) {
                                if (sourceEventMap[key].every((_key) => common.isString(_key))) {
                                    _outputEventMap[`ON`] = sourceEventMap[key].reduce((onEventMap, _key) => {
                                        onEventMap[
                                            dashToUpperCaseUnderscore(_key)
                                        ] = `on-${_key}`;
                                        return onEventMap;
                                    }, {});
                                } else {
                                    common.log(`error`, `Event.create - Input 'on' event keys are invalid.`);
                                }
                            }
                            if (key === `doEvents`) {
                                if (sourceEventMap[key].every((_key) => common.isString(_key))) {
                                    _outputEventMap[`DO`] = sourceEventMap[key].reduce((doEventMap, _key) => {
                                        doEventMap[
                                            dashToUpperCaseUnderscore(_key)
                                        ] = `do-${_key}`;
                                        return doEventMap;
                                    }, {});
                                } else {
                                    common.log(`error`, `Event.create - Input 'do' event keys are invalid.`);
                                }
                            }
                            if (key === `broadcastEvents`) {
                                if (sourceEventMap[key].every((_key) => common.isString(_key))) {
                                    _outputEventMap[`BROADCAST`] = sourceEventMap[key].reduce((broadcastEventMap, _key) => {
                                        broadcastEventMap[
                                            dashToUpperCaseUnderscore(_key)
                                        ] = `broadcast-${_key}`;
                                        return broadcastEventMap;
                                    }, {});
                                } else {
                                    common.log(`error`, `Event.create - Input 'broadcast' event keys are invalid.`);
                                }
                            }
                            if (key === `requestEvents`) {
                                if (sourceEventMap[key].every((_key) => common.isString(_key))) {
                                    _outputEventMap[`REQUEST`] = sourceEventMap[key].reduce((requestForEventMap, _key) => {
                                        requestForEventMap[
                                            dashToUpperCaseUnderscore(_key)
                                        ] = `request-for-${_key}`;
                                        return requestForEventMap;
                                    }, {});
                                    _outputEventMap[`RESPONSE`] = {
                                        WITH: sourceEventMap[key].reduce((responseToEventMap, _key) => {
                                            responseToEventMap[
                                                dashToUpperCaseUnderscore(_key)
                                            ] = `response-with-${_key}`;
                                            return responseToEventMap;
                                        }, {}),
                                        TO: sourceEventMap[key].reduce((responseToEventMap, _key) => {
                                            responseToEventMap[
                                                dashToUpperCaseUnderscore(_key)
                                            ] = {
                                                OK: `response-to-${_key}-ok`,
                                                ERROR: `response-to-${_key}-error`,
                                                CONFLICT: `response-to-${_key}-conflict`,
                                                NOT_FOUND: `response-to-${_key}-not-found`,
                                                NOT_MODIFIED: `response-to-${_key}-not-modified`,
                                                UNAUTHORIZED: `response-to-${_key}-unauthorized`
                                            };
                                            return responseToEventMap;
                                        }, {})
                                    };
                                } else {
                                    common.log(`error`, `Event.create - Input 'request-for' event keys are invalid.`);
                                }
                            }
                            return _outputEventMap;
                        }, {});
                        // return Object.freeze(outputEventMap);
                        return outputEventMap;
                    }
                }
            },
            /* set store, interface, domain, and service factory namespaces */
            Domain: DomainFactory,
            Store: StoreFactory,
            Interface: InterfaceFactory,
            Service: ServiceFactory,
            /* set app factory namespace */
            App: AppFactory,
            /* set test agent & fixtures factory namespace */
            Agent: AgentFactory,
            // Fixture: FixtureFactory,
            /* set state composite factory namespace */
            State: {
                ReducerComposite: StateReducerComposite,
                TimeTraversalComposite: StateTimeTraversalComposite
            },
            /* set test fixtures composites namespace */
            // Test: {
            //     TapeRunnerComposite: TapeTestRunnerComposite,
            //     DomainFixtureComposite: DomainTestFixtureComposite,
            //     StoreFixtureComposite: StoreTestFixtureComposite,
            //     InterfaceFixtureComposite: InterfaceTestFixtureComposite,
            //     ServiceFixtureComposite: ServiceTestFixtureComposite
            // },
            /* set composite library namespace */
            React: {
                ComponentComposite: ReactComponentComposite,
                AppComponentComposite: (() => {
                    switch (TARGET) { // eslint-disable-line
                    case `client-native`:
                        return ReactClientNativeAppComponentComposite;
                    case `client-web`:
                        return ReactClientWebAppComponentComposite;
                    case `server`:
                        return ReactServerAppComponentComposite;
                    }
                })(),
                AppRendererComposite: (() => {
                    switch (TARGET) { // eslint-disable-line
                    case `client-native`:
                        return ReactClientNativeAppRendererComposite;
                    case `client-web`:
                        return ReactClientWebAppRendererComposite;
                    case `server`:
                        return ReactServerAppRendererComposite;
                    }
                })()
            },
            Storage: (() => {
                switch (TARGET) { // eslint-disable-line
                case `client-native`:
                    return {
                        ASyncStorageComposite
                    };
                case `client-web`:
                    return {
                        WebStorageComposite
                    };
                case `server`:
                    return {
                        PGComposite
                    };
                }
            })()
        };

        /* create an initialized Hflow object */
        Hflow = Object.freeze(common.mix(common, {
            exclusion: {
                /* hide reveal method, reveal is for internal use only */
                keys: [
                    `reveal`
                ]
            }
        }).with(HflowProperty));
    }
    return Hflow;
};

export {
    Hflow,
    init
};
<|endoftext|>