text:
<?php

namespace Grav\Framework\Collection;

use ArrayIterator;
use Closure;
use Grav\Framework\Compat\Serializable;
use Grav\Framework\Flex\Interfaces\FlexObjectInterface;
use InvalidArgumentException;
use Iterator;
use function array_key_exists;
use function array_slice;
use function count;

/**
 * Abstract Index Collection.
 * @template TKey of array-key
 * @template T
 * @template C of CollectionInterface
 * @implements CollectionInterface<TKey,T>
 */
abstract class AbstractIndexCollection implements CollectionInterface
{
    use Serializable;

    /**
     * @var array
     * @phpstan-var array<TKey,T>
     */
    private $entries;

    /**
     * Initializes a new IndexCollection.
     *
     * @param array $entries
     * @phpstan-param array<TKey,T> $entries
     */
    public function __construct(array $entries = [])
    {
        $this->entries = $entries;
    }

    /**
     * {@inheritDoc}
     */
    public function toArray()
    {
        return $this->loadElements($this->entries);
    }

    /**
     * {@inheritDoc}
     */
    public function first()
    {
        $value = reset($this->entries);
        $key = (string)key($this->entries);

        return $this->loadElement($key, $value);
    }

    /**
     * {@inheritDoc}
     */
    public function last()
    {
        $value = end($this->entries);
        $key = (string)key($this->entries);

        return $this->loadElement($key, $value);
    }

    /**
     * {@inheritDoc}
     */
    #[\ReturnTypeWillChange]
    public function key()
    {
        /** @phpstan-var TKey */
        return (string)key($this->entries);
    }

    /**
     * {@inheritDoc}
     */
    #[\ReturnTypeWillChange]
    public function next()
    {
        $value = next($this->entries);
        $key = (string)key($this->entries);

        return $this->loadElement($key, $value);
    }

    /**
     * {@inheritDoc}
     */
    #[\ReturnTypeWillChange]
    public function current()
    {
        $value = current($this->entries);
        $key = (string)key($this->entries);

        return $this->loadElement($key, $value);
    }

    /**
     * {@inheritDoc}
     */
    public function remove($key)
    {
        if (!array_key_exists($key, $this->entries)) {
            return null;
        }

        $value = $this->entries[$key];
        unset($this->entries[$key]);

        return $this->loadElement((string)$key, $value);
    }

    /**
     * {@inheritDoc}
     */
    public function removeElement($element)
    {
        $key = $this->isAllowedElement($element) ? $this->getCurrentKey($element) : null;

        if (null !== $key || !isset($this->entries[$key])) {
            return false;
        }

        unset($this->entries[$key]);

        return true;
    }

    /**
     * Required by interface ArrayAccess.
     *
     * @param string|int|null $offset
     * @return bool
     * @phpstan-param TKey|null $offset
     */
    #[\ReturnTypeWillChange]
    public function offsetExists($offset)
    {
        /** @phpstan-ignore-next-line phpstan bug? */
        return $offset !== null ? $this->containsKey($offset) : false;
    }

    /**
     * Required by interface ArrayAccess.
     *
     * @param string|int|null $offset
     * @return mixed
     * @phpstan-param TKey|null $offset
     */
    #[\ReturnTypeWillChange]
    public function offsetGet($offset)
    {
        /** @phpstan-ignore-next-line phpstan bug? */
        return $offset !== null ? $this->get($offset) : null;
    }

    /**
     * Required by interface ArrayAccess.
     *
     * @param string|int|null $offset
     * @param mixed $value
     * @return void
     * @phpstan-param TKey|null $offset
     */
    #[\ReturnTypeWillChange]
    public function offsetSet($offset, $value)
    {
        if (null === $offset) {
            $this->add($value);
        } else {
            /** @phpstan-ignore-next-line phpstan bug? */
            $this->set($offset, $value);
        }
    }

    /**
     * Required by interface ArrayAccess.
     *
     * @param string|int|null $offset
     * @return void
     * @phpstan-param TKey|null $offset
     */
    #[\ReturnTypeWillChange]
    public function offsetUnset($offset)
    {
        if ($offset !== null) {
            /** @phpstan-ignore-next-line phpstan bug? */
            $this->remove($offset);
        }
    }

    /**
     * {@inheritDoc}
     */
    public function containsKey($key)
    {
        return isset($this->entries[$key]) || array_key_exists($key, $this->entries);
    }

    /**
     * {@inheritDoc}
     */
    public function contains($element)
    {
        $key = $this->isAllowedElement($element) ? $this->getCurrentKey($element) : null;

        return $key && isset($this->entries[$key]);
    }

    /**
     * {@inheritDoc}
     */
    public function exists(Closure $p)
    {
        return $this->loadCollection($this->entries)->exists($p);
    }

    /**
     * {@inheritDoc}
     */
    public function indexOf($element)
    {
        $key = $this->isAllowedElement($element) ? $this->getCurrentKey($element) : null;

        return $key && isset($this->entries[$key]) ? $key : false;
    }

    /**
     * {@inheritDoc}
     */
    public function get($key)
    {
        if (!isset($this->entries[$key])) {
            return null;
        }

        return $this->loadElement((string)$key, $this->entries[$key]);
    }

    /**
     * {@inheritDoc}
     */
    public function getKeys()
    {
        return array_keys($this->entries);
    }

    /**
     * {@inheritDoc}
     */
    public function getValues()
    {
        return array_values($this->loadElements($this->entries));
    }

    /**
     * {@inheritDoc}
     */
    #[\ReturnTypeWillChange]
    public function count()
    {
        return count($this->entries);
    }

    /**
     * {@inheritDoc}
     */
    public function set($key, $value)
    {
        if (!$this->isAllowedElement($value)) {
            throw new InvalidArgumentException('Invalid argument $value');
        }

        $this->entries[$key] = $this->getElementMeta($value);
    }

    /**
     * {@inheritDoc}
     */
    public function add($element)
    {
        if (!$this->isAllowedElement($element)) {
            throw new InvalidArgumentException('Invalid argument $element');
        }

        $this->entries[$this->getCurrentKey($element)] = $this->getElementMeta($element);

        return true;
    }

    /**
     * {@inheritDoc}
     */
    public function isEmpty()
    {
        return empty($this->entries);
    }

    /**
     * Required by interface IteratorAggregate.
     *
     * {@inheritDoc}
     * @phpstan-return Iterator<TKey,T>
     */
    #[\ReturnTypeWillChange]
    public function getIterator()
    {
        return new ArrayIterator($this->loadElements());
    }

    /**
     * {@inheritDoc}
     */
    public function map(Closure $func)
    {
        return $this->loadCollection($this->entries)->map($func);
    }

    /**
     * {@inheritDoc}
     */
    public function filter(Closure $p)
    {
        return $this->loadCollection($this->entries)->filter($p);
    }

    /**
     * {@inheritDoc}
     */
    public function forAll(Closure $p)
    {
        return $this->loadCollection($this->entries)->forAll($p);
    }

    /**
     * {@inheritDoc}
     */
    public function partition(Closure $p)
    {
        return $this->loadCollection($this->entries)->partition($p);
    }

    /**
     * Returns a string representation of this object.
     *
     * @return string
     */
    #[\ReturnTypeWillChange]
    public function __toString()
    {
        return __CLASS__ . '@' . spl_object_hash($this);
    }

    /**
     * {@inheritDoc}
     */
    public function clear()
    {
        $this->entries = [];
    }

    /**
     * {@inheritDoc}
     */
    public function slice($offset, $length = null)
    {
        return $this->loadElements(array_slice($this->entries, $offset, $length, true));
    }

    /**
     * @param int $start
     * @param int|null $limit
     * @return static
     * @phpstan-return static<TKey,T,C>
     */
    public function limit($start, $limit = null)
    {
        return $this->createFrom(array_slice($this->entries, $start, $limit, true));
    }

    /**
     * Reverse the order of the items.
     *
     * @return static
     * @phpstan-return static<TKey,T,C>
     */
    public function reverse()
    {
        return $this->createFrom(array_reverse($this->entries));
    }

    /**
     * Shuffle items.
     *
     * @return static
     * @phpstan-return static<TKey,T,C>
     */
    public function shuffle()
    {
        $keys = $this->getKeys();
        shuffle($keys);

        return $this->createFrom(array_replace(array_flip($keys), $this->entries));
    }

    /**
     * Select items from collection.
     *
     * Collection is returned in the order of $keys given to the function.
     *
     * @param array $keys
     * @return static
     * @phpstan-return static<TKey,T,C>
     */
    public function select(array $keys)
    {
        $list = [];
        foreach ($keys as $key) {
            if (isset($this->entries[$key])) {
                $list[$key] = $this->entries[$key];
            }
        }

        return $this->createFrom($list);
    }

    /**
     * Un-select items from collection.
     *
     * @param array $keys
     * @return static
     * @phpstan-return static<TKey,T,C>
     */
    public function unselect(array $keys)
    {
        return $this->select(array_diff($this->getKeys(), $keys));
    }

    /**
     * Split collection into chunks.
     *
     * @param int $size     Size of each chunk.
     * @return array
     * @phpstan-return array<array<TKey,T>>
     */
    public function chunk($size)
    {
        /** @phpstan-var array<array<TKey,T>> */
        return $this->loadCollection($this->entries)->chunk($size);
    }

    /**
     * @return array
     */
    public function __serialize(): array
    {
        return [
            'entries' => $this->entries
        ];
    }

    /**
     * @param array $data
     * @return void
     */
    public function __unserialize(array $data): void
    {
        $this->entries = $data['entries'];
    }

    /**
     * Implements JsonSerializable interface.
     *
     * @return array
     */
    #[\ReturnTypeWillChange]
    public function jsonSerialize()
    {
        return $this->loadCollection()->jsonSerialize();
    }

    /**
     * Creates a new instance from the specified elements.
     *
     * This method is provided for derived classes to specify how a new
     * instance should be created when constructor semantics have changed.
     *
     * @param array $entries Elements.
     * @return static
     * @phpstan-return static<TKey,T,C>
     */
    protected function createFrom(array $entries)
    {
        return new static($entries);
    }

    /**
     * @return array
     */
    protected function getEntries(): array
    {
        return $this->entries;
    }

    /**
     * @param array $entries
     * @return void
     * @phpstan-param array<TKey,T> $entries
     */
    protected function setEntries(array $entries): void
    {
        $this->entries = $entries;
    }

    /**
     * @param FlexObjectInterface $element
     * @return string
     * @phpstan-param T $element
     * @phpstan-return TKey
     */
    protected function getCurrentKey($element)
    {
        return $element->getKey();
    }

    /**
     * @param string $key
     * @param mixed $value
     * @return mixed|null
     */
    abstract protected function loadElement($key, $value);

    /**
     * @param array|null $entries
     * @return array
     * @phpstan-return array<TKey,T>
     */
    abstract protected function loadElements(array $entries = null): array;

    /**
     * @param array|null $entries
     * @return CollectionInterface
     * @phpstan-return C
     */
    abstract protected function loadCollection(array $entries = null): CollectionInterface;

    /**
     * @param mixed $value
     * @return bool
     */
    abstract protected function isAllowedElement($value): bool;

    /**
     * @param mixed $element
     * @return mixed
     */
    abstract protected function getElementMeta($element);
}


text:
<template name="about">

Problem Description:

Java verion  for Java lovers

When I input the employee's details: first name, last name, annual salary(positive integer) and super rate(0% - 50% inclusive), payment start date, the program should generate payslip information with name, pay period,  gross income, income tax, net income and super.

The calculation details will be the following:
•       pay period = per calendar month
•       gross income = annual salary / 12 months
•       income tax = based on the tax table provide below
•       net income = gross income - income tax
•       super = gross income x super rate

Notes: All calculation results should be rounded to the whole dollar. If >= 50 cents round up to the next dollar increment, otherwise round down.

The following rates for 2012-13 apply from 1 July 2012.

Taxable income   Tax on this income
0 - $18,200     Nil
$18,201 - $37,000       19c for each $1 over $18,200
$37,001 - $80,000       $3,572 plus 32.5c for each $1 over $37,000
$80,001 - $180,000      $17,547 plus 37c for each $1 over $80,000
$180,001 and over       $54,547 plus 45c for each $1 over $180,000

Example Data
Employee annual salary is 60,050, super rate is 9%, how much will this employee be paid for the month of March ?
•       pay period = Month of March (01 March to 31 March)
•       gross income = 60,050 / 12 = 5,004.16666667 (round down) = 5,004
•       income tax = (3,572 + (60,050 - 37,000) x 0.325) / 12  = 921.9375 (round up) = 922
•       net income = 5,004 - 922 = 4,082
•       super = 5,004 x 9% = 450.36 (round down) = 450

Solution

Hackathon approach.
Build fast, realible web / hibrid apps in a couple of hours. The implememtatiom uses Meteor JS and uses Differential boilerplate as starting point for giving a richer U/X Experince.

Load a CSV file

Whilst parsing - calculate payslip

Store it to Mongo

Display results!

Build

Install meteor with: curl https://install.meteor.com/ | sh

git clone https://github.com/marquinhe/tax-meteor

rm -rf .git

meteor

Stuff used to make this:

meteor Meteor framework > node js, mongo, blaze, ironLrouter ....

Differential Boilerplate for the awesome UX

PapaPArse CSV Parser

</template>

redpajama_set_name: RedPajamaGithub


text:
**Read More**

[Managing Events](https://docs.wavefront.com/events.html)

[Basic events() Queries](https://docs.wavefront.com/events_queries.html)

[Advanced events() Queries](https://docs.wavefront.com/events_queries_advanced.html)

**Watch Videos**

[Introduction to Events](https://vmwaretv.vmware.com/media/t/1_sq8p1jhk/252649793)


text:
<?xml version="1.0" encoding="ascii"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
          "DTD/xhtml1-transitional.dtd">

  <title>actuator.namespace.VarFuture</title>
  <link rel="stylesheet" href="epydoc.css" type="text/css" />

         Home

         Trees

         Indices

         Help

Actuator

        Package actuator ::
        Module namespace ::
        Class VarFuture

[hide private]

[frames] | no frames]

Class VarFuture

source code

object --+
         |
        VarFuture

A wrapper that allows a Var to be treated like reference into a model.
  Supports a value() method that allows deferring the computation of the
  variable until the value is needed. These are created by the future()
  method of VariableContainer

        Instance Methods
        [hide private]

          __init__(self,
        var,
        context)

      Create a new VarFuture

            source code

          value(self,
        allow_unexpanded=False)

      Compute the value of the Var from the perspective of the context.

            source code

Inherited from object:
      __delattr__,
      __format__,
      __getattribute__,
      __hash__,
      __new__,
      __reduce__,
      __reduce_ex__,
      __repr__,
      __setattr__,
      __sizeof__,
      __str__,
      __subclasshook__

        Properties
        [hide private]

Inherited from object:
      __class__

        Method Details
        [hide private]

__init__(self,
        var,
        context)

(Constructor)

  	source code

Create a new VarFuture

Parameters:

var - A Var object

context - A kind of VariableContainer from which the Var's value can be
          computed.

Overrides:
        object.__init__

value(self,
        allow_unexpanded=False)

  	source code

Compute the value of the Var from the perspective of the context.

Parameters:

allow_unexpanded - Optional, default False. Indicates what to return if the Var
          can't be fully expanded (all replacement patterns can not be
          resolved). The default, False, means that if all patterns can't
          be replaced then return None as the result, which is only
          possible for unset values or for patterns that can't be replaced.
          If allow_unexpanded is True, return the result with as much as
          could be replaced.

         Home

         Trees

         Indices

         Help

Actuator

    Generated by Epydoc 3.0.1 on Mon Feb  9 18:19:52 2015

      http://epydoc.sourceforge.net


text:
"use strict";

var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.XPathWildcardAnywhereElement = void 0;
// CONVERSTION complete, Burt Harris 10/14/2016
const Decorators_1 = require("../../Decorators");
const Trees_1 = require("../Trees");
const XPath_1 = require("./XPath");
const XPathElement_1 = require("./XPathElement");
class XPathWildcardAnywhereElement extends XPathElement_1.XPathElement {
    constructor() {
        super(XPath_1.XPath.WILDCARD);
    }
    evaluate(t) {
        if (this.invert) {
            // !* is weird but valid (empty)
            return [];
        }
        return Trees_1.Trees.getDescendants(t);
    }
}
__decorate([
    Decorators_1.Override
], XPathWildcardAnywhereElement.prototype, "evaluate", null);
exports.XPathWildcardAnywhereElement = XPathWildcardAnywhereElement;
//# sourceMappingURL=XPathWildcardAnywhereElement.js.map


text:
package org.pentaho.big.data.kettle.plugins.pig;

import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.VFS;
import org.apache.pig.PigServer;
import org.apache.pig.tools.grunt.GruntParser;
import org.pentaho.big.data.api.initializer.ClusterInitializer;
import org.pentaho.big.data.impl.cluster.NamedClusterManager;
import org.pentaho.big.data.impl.shim.pig.PigServiceFactoryImpl;
import org.pentaho.bigdata.api.pig.PigServiceFactory;
import org.pentaho.bigdata.api.pig.impl.PigServiceLocatorImpl;
import org.pentaho.di.core.annotations.JobEntry;
import org.pentaho.hadoop.shim.ConfigurationException;
import org.pentaho.hadoop.shim.HadoopConfiguration;
import org.pentaho.hadoop.shim.common.CommonHadoopShim;
import org.pentaho.hadoop.shim.common.CommonPigShim;
import org.pentaho.hadoop.shim.common.CommonSqoopShim;
import org.pentaho.hadoop.shim.spi.HadoopConfigurationProvider;

import java.io.StringReader;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

import static org.mockito.Mockito.mock;

/**
 * Created by bryan on 7/15/15.
 */
@JobEntry( id = "HadoopPigScriptExecutorPlugin", image = "PIG.svg", name = "HadoopPigScriptExecutorPlugin.Name",
  description = "HadoopPigScriptExecutorPlugin.Description",
  categoryDescription = "i18n:org.pentaho.di.job:JobCategory.Category.BigData",
  i18nPackageName = "org.pentaho.di.job.entries.pig",
  documentationUrl = "http://wiki.pentaho.com/display/EAI/Pig+Script+Executor" )
public class NoArgJobEntryPigScriptExecutor extends JobEntryPigScriptExecutor {
  private static final HadoopConfigurationProvider provider = initProvider();

  public NoArgJobEntryPigScriptExecutor() throws FileSystemException, ConfigurationException {
    super( new NamedClusterManager(), new PigServiceLocatorImpl( Arrays.<PigServiceFactory>asList(
      new PigServiceFactoryImpl( true, provider.getConfiguration( null ) ) ), mock( ClusterInitializer.class ) ) );
  }

  public static HadoopConfigurationProvider getProvider() {
    return provider;
  }

  private static HadoopConfigurationProvider initProvider() {
    try {
      return new TestProvider();
    } catch ( FileSystemException e ) {
      e.printStackTrace();
      return null;
    }
  }

  static class TestProvider implements HadoopConfigurationProvider {
    HadoopConfiguration config;

    TestProvider() throws FileSystemException {
      config = new HadoopConfiguration( VFS.getManager().resolveFile( "ram:///" ), "test", "test",
        new CommonHadoopShim(), new CommonSqoopShim(), new TestPigShim() );
    }

    @Override
    public boolean hasConfiguration( String id ) {
      return true;
    }

    @Override
    public List<? extends HadoopConfiguration> getConfigurations() {
      return Arrays.asList( config );
    }

    @Override
    public HadoopConfiguration getConfiguration( String id ) throws ConfigurationException {
      return config;
    }

    @Override
    public HadoopConfiguration getActiveConfiguration() throws ConfigurationException {
      return config;
    }
  }

  static class TestPigShim extends CommonPigShim {
    @Override public int[] executeScript( String pigScript, ExecutionMode executionMode, Properties properties )
      throws Exception {
      ClassLoader cl = Thread.currentThread().getContextClassLoader();
      Thread.currentThread().setContextClassLoader( getClass().getClassLoader() );
      try {
        PigServer pigServer = new PigServer( getExecType( executionMode ), properties );
        GruntParser grunt = new GruntParser( new StringReader( pigScript ) );
        grunt.setInteractive( false );
        grunt.setParams( pigServer );
        return grunt.parseStopOnError( false );
      } finally {
        Thread.currentThread().setContextClassLoader( cl );
      }
    }
  }
}


text:
<?xml version="1.0" encoding="utf-8"?>
<selector
  xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/bg_list_pressed" />
    <item android:state_focused="true" android:drawable="@drawable/bg_list_focused" />
    <item android:state_selected="true" android:drawable="@drawable/bg_list_focused" />
    <item android:drawable="@drawable/bg_list_focused" />
</selector>


text:
require 'acts_as_amico'

Amico.configure do |configuration|
  configuration.redis = Redis.new
  configuration.namespace = 'acts_as_amico'
  configuration.following_key = 'following'
  configuration.followers_key = 'followers'
  configuration.blocked_key = 'blocked'
  configuration.reciprocated_key = 'reciprocated'
  configuration.pending_key = 'pending'
  configuration.default_scope_key = 'user'
  configuration.pending_follow = false
  configuration.page_size = 25
end


text:
<?php

namespace PHPExiftool\Driver\Tag\DICOM;

use JMS\Serializer\Annotation\ExclusionPolicy;
use PHPExiftool\Driver\AbstractTag;

/**
 * @ExclusionPolicy("all")
 */
class TreatmentSummaryMeasuredDoseRefSeq extends AbstractTag
{

    protected $Id = '3008,00E0';

    protected $Name = 'TreatmentSummaryMeasuredDoseRefSeq';

    protected $FullName = 'DICOM::Main';

    protected $GroupName = 'DICOM';

    protected $g0 = 'DICOM';

    protected $g1 = 'DICOM';

    protected $g2 = 'Image';

    protected $Type = '?';

    protected $Writable = false;

    protected $Description = 'Treatment Summary Measured Dose Ref Seq';

}


text:
package io.grpc.alts.internal;

import static com.google.common.truth.Truth.assertThat;

import io.grpc.alts.internal.TransportSecurityCommon.RpcProtocolVersions;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Unit tests for {@link AltsClientOptions}. */
@RunWith(JUnit4.class)
public final class AltsClientOptionsTest {

  @Test
  public void setAndGet() throws Exception {
    String targetName = "foo";
    String serviceAccount1 = "bar1";
    String serviceAccount2 = "bar2";
    RpcProtocolVersions rpcVersions =
        RpcProtocolVersions.newBuilder()
            .setMaxRpcVersion(
                RpcProtocolVersions.Version.newBuilder().setMajor(2).setMinor(1).build())
            .setMinRpcVersion(
                RpcProtocolVersions.Version.newBuilder().setMajor(2).setMinor(1).build())
            .build();

    AltsClientOptions options =
        new AltsClientOptions.Builder()
            .setTargetName(targetName)
            .addTargetServiceAccount(serviceAccount1)
            .addTargetServiceAccount(serviceAccount2)
            .setRpcProtocolVersions(rpcVersions)
            .build();

    assertThat(options.getTargetName()).isEqualTo(targetName);
    assertThat(options.getTargetServiceAccounts()).containsAllOf(serviceAccount1, serviceAccount2);
    assertThat(options.getRpcProtocolVersions()).isEqualTo(rpcVersions);
  }
}


text:
import Immutable from 'immutable';

const actions = {
  CREATE_POST: "CREATE_POST",
  DELETE_POST: "DELETE_POST"
};

var nextId = 0;

const fixtures = Immutable.List([{id: 0, content: "meow im a post"}]);

const posts = (state = fixtures, action) => {
  switch (action.type) {
    case (actions.CREATE_POST):
      nextId++;
      return (
        state.concat([{
          id: nextId,
          content: action.content
        }])
      );
      break;
    case (actions.DELETE_POST):
      return (
        state.filter( value => value.id != action.id )
      );
      break;
    default:
      return state;

  }
}

export default posts;


text:
#ifndef IDBFactoryBackendInterface_h
#define IDBFactoryBackendInterface_h

#include "wtf/PassRefPtr.h"
#include "wtf/RefCounted.h"
#include "wtf/text/WTFString.h"

namespace WebCore {

class IDBCallbacks;
class IDBDatabase;
class IDBDatabaseCallbacks;
class ScriptExecutionContext;

typedef int ExceptionCode;

// This class is shared by IDBFactory (async) and IDBFactorySync (sync).
// This is implemented by IDBFactoryBackendImpl and optionally others (in order to proxy
// calls across process barriers). All calls to these classes should be non-blocking and
// trigger work on a background thread if necessary.
class IDBFactoryBackendInterface : public RefCounted<IDBFactoryBackendInterface> {
public:
    static PassRefPtr<IDBFactoryBackendInterface> create();
    virtual ~IDBFactoryBackendInterface() { }

    virtual void getDatabaseNames(PassRefPtr<IDBCallbacks>, const String& databaseIdentifier, ScriptExecutionContext*, const String& dataDir) = 0;
    virtual void open(const String& name, int64_t version, int64_t transactionId, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBDatabaseCallbacks>, const String& databaseIdentifier, ScriptExecutionContext*, const String& dataDir) = 0;
    virtual void deleteDatabase(const String& name, PassRefPtr<IDBCallbacks>, const String& databaseIdentifier, ScriptExecutionContext*, const String& dataDir) = 0;
};

} // namespace WebCore

#endif // IDBFactoryBackendInterface_h


text:
/*	$NetBSD: devopen.c,v 1.1 2002/02/27 21:02:26 scw Exp $	*/

#include <sys/param.h>
#include <stand.h>

/*
 * Open the device named by the combined device/file name
 * given as the "fname" arg, something like: "sd()bsd"
 *
 * However, Sun PROMs don't really let you choose which
 * device you will talk to.  You can only open the device
 * that was used to load the boot program.  Therefore, we
 * do not accept a "device" part in the "fname" string.
 * Pass the PROM device name to open in case it needs it.
 */
int
devopen(f, fname, file)
	struct open_file *f;
	const char *fname;
	char **file;
{
	struct devsw *dp;
	int error;

	*file = (char*)fname;
	dp = &devsw[0];
	f->f_dev = dp;
	error = (*dp->dv_open)(f, "net");	/* XXXSCW: Fixme */

	return (error);
}


text:
import { expect } from "chai";
import * as _ from "lodash";
import * as nock from "nock";
import * as querystring from "querystring";

import {
  AlexaEvent,
  AlexaPlatform,
  AlexaReply,
  EventBuilder,
  GARBAGE_COLLECTION_DAY,
  GARBAGE_TYPE,
  MEDIA_CONTENT_METHOD,
  MEDIA_CONTENT_TYPE,
  MediaContentEventBuilder,
  MESSAGE_ALERT_FRESHNESS,
  MESSAGE_ALERT_STATUS,
  MESSAGE_ALERT_URGENCY,
  MessageAlertEventBuilder,
  OCCASION_CONFIRMATION_STATUS,
  OCCASION_TYPE,
  OccasionEventBuilder,
  ORDER_STATUS,
  OrderStatusEventBuilder,
  ProactiveEvents,
  SOCIAL_GAME_INVITE_TYPE,
  SOCIAL_GAME_OFFER,
  SOCIAL_GAME_RELATIONSHIP_TO_INVITEE,
  SocialGameInviteEventBuilder,
  SportsEventBuilder,
  TrashCollectionAlertEventBuilder,
  VoxaApp,
  WEATHER_ALERT_TYPE,
  WeatherAlertEventBuilder,
} from "../../src";
import { AlexaRequestBuilder } from "./../tools";
import { variables } from "./../variables";
import { views } from "./../views";

const rb = new AlexaRequestBuilder();

const clientId: string = "clientId";
const clientSecret: string = "clientSecret";

describe("ProactiveEvents", () => {
  const tokenResponse = {
    access_token: "Atc|MQEWYJxEnP3I1ND03ZzbY_NxQkA7Kn7Aioev_OfMRcyVQ4NxGzJMEaKJ8f0lSOiV-yW270o6fnkI",
    expires_in: 3600,
    scope: "alexa::proactive_events",
    token_type: "Bearer",
  };
  let reqheaders: any = {};

  beforeEach(() => {
    reqheaders = {
      "accept": "application/json",
      "content-length": 105,
      "content-type": "application/x-www-form-urlencoded",
      "host": "api.amazon.com",
    };

    const bodyRequest = {
      client_id: clientId,
      client_secret: clientSecret,
      grant_type: "client_credentials",
      scope: "alexa::proactive_events",
    };

    const body = decodeURIComponent(querystring.stringify(bodyRequest));

    nock("https://api.amazon.com", { reqheaders })
      .post("/auth/O2/token", body)
      .reply(200, JSON.stringify(tokenResponse));
  });

  afterEach(() => {
    nock.cleanAll();
  });

  it("should get a new access token and send a WeatherAlert event", async () => {
    reqheaders = {
      "accept": "application/json",
      "authorization": `Bearer ${tokenResponse.access_token}`,
      "content-length": 389,
      "content-type": "application/json",
      "host": "api.amazonalexa.com",
    };

    const userId = "userId";
    const endpoint: string = "https://api.amazonalexa.com";

    const event: WeatherAlertEventBuilder = new WeatherAlertEventBuilder();
    event
      .setHurricane()
      .setSnowStorm()
      .setThunderStorm()
      .setTornado()
      .addContent("en-US", "source", "CNN")
      .addContent("en-GB", "source", "BBC")
      .setReferenceId("referenceId1")
      .setTimestamp("2018-12-19T21:56:24.00Z")
      .setExpiryTime("2018-12-19T22:57:24.00Z")
      .setMulticast();

    nock(endpoint, { reqheaders })
      .post("/v1/proactiveEvents/stages/development", event.build())
      .reply(200);

    const proactiveEvents = new ProactiveEvents(clientId, clientSecret);
    const messageResponse = await proactiveEvents.createEvent(endpoint, event, true);

    expect(messageResponse).to.be.undefined;
  });

  it("should get a new access token and send a SportsEvent event", async () => {
    reqheaders = {
      "accept": "application/json",
      "authorization": `Bearer ${tokenResponse.access_token}`,
      "content-length": 604,
      "content-type": "application/json",
      "host": "api.amazonalexa.com",
    };

    const userId = "userId";
    const endpoint: string = "https://api.amazonalexa.com";

    const event: SportsEventBuilder = new SportsEventBuilder();
    event
      .setAwayTeamStatistic("Boston Red Sox", 5)
      .setHomeTeamStatistic("New York Yankees", 2)
      .setUpdate("Boston Red Sox", 5)
      .addContent("en-US", "eventLeagueName", "CNN")
      .addContent("en-GB", "eventLeagueName", "BBC")
      .setReferenceId("referenceId1")
      .setTimestamp("2018-12-19T21:56:24.00Z")
      .setExpiryTime("2018-12-19T22:57:24.00Z")
      .setMulticast()
      .setUnicast("userId");

    nock(endpoint, { reqheaders })
      .post("/v1/proactiveEvents/stages/development", event.build())
      .reply(200);

    const proactiveEvents = new ProactiveEvents(clientId, clientSecret);
    const messageResponse = await proactiveEvents.createEvent(endpoint, event, true);

    expect(messageResponse).to.be.undefined;
  });

  it("should get a new access token and send a MessageAlert event", async () => {
    reqheaders = {
      "accept": "application/json",
      "authorization": `Bearer ${tokenResponse.access_token}`,
      "content-length": 366,
      "content-type": "application/json",
      "host": "api.amazonalexa.com",
    };

    const userId = "userId";
    const endpoint: string = "https://api.amazonalexa.com";

    const event: MessageAlertEventBuilder = new MessageAlertEventBuilder();
    event
      .setMessageGroup("Friend", 2, MESSAGE_ALERT_URGENCY.URGENT)
      .setState(MESSAGE_ALERT_STATUS.UNREAD, MESSAGE_ALERT_FRESHNESS.NEW)
      .setReferenceId("referenceId1")
      .setTimestamp("2018-12-19T21:56:24.00Z")
      .setExpiryTime("2018-12-19T22:57:24.00Z")
      .setMulticast();

    nock(endpoint, { reqheaders })
      .post("/v1/proactiveEvents/stages/development", event.build())
      .reply(200);

    const proactiveEvents = new ProactiveEvents(clientId, clientSecret);
    const messageResponse = await proactiveEvents.createEvent(endpoint, event, true);

    expect(messageResponse).to.be.undefined;
  });

  it("should get a new access token and send a OrderStatus event", async () => {
    reqheaders = {
      "accept": "application/json",
      "authorization": `Bearer ${tokenResponse.access_token}`,
      "content-length": 522,
      "content-type": "application/json",
      "host": "api.amazonalexa.com",
    };

    const userId = "userId";
    const endpoint: string = "https://api.amazonalexa.com";

    const event: OrderStatusEventBuilder = new OrderStatusEventBuilder();
    event
      .setStatus(ORDER_STATUS.ORDER_DELIVERED, "2018-12-19T22:56:24.00Z", "2018-12-19T22:56:24.00Z")
      .addContent("en-US", "sellerName", "CNN")
      .addContent("en-GB", "sellerName", "BBC")
      .setReferenceId("referenceId1")
      .setTimestamp("2018-12-19T21:56:24.00Z")
      .setExpiryTime("2018-12-19T22:57:24.00Z")
      .setMulticast();

    nock(endpoint, { reqheaders })
      .post("/v1/proactiveEvents/stages/development", event.build())
      .reply(200);

    const proactiveEvents = new ProactiveEvents(clientId, clientSecret);
    const messageResponse = await proactiveEvents.createEvent(endpoint, event, true);

    expect(messageResponse).to.be.undefined;
  });

  it("should get a new access token and send a Occasion event", async () => {
    reqheaders = {
      "accept": "application/json",
      "authorization": `Bearer ${tokenResponse.access_token}`,
      "content-length": 717,
      "content-type": "application/json",
      "host": "api.amazonalexa.com",
    };

    const userId = "userId";
    const endpoint: string = "https://api.amazonalexa.com";

    const event: OccasionEventBuilder = new OccasionEventBuilder();
    event
      .setOccasion("2018-12-19T22:56:24.00Z", OCCASION_TYPE.APPOINTMENT)
      .setStatus(OCCASION_CONFIRMATION_STATUS.CONFIRMED)
      .addContent("en-US", "brokerName", "CNN Chicago")
      .addContent("en-GB", "brokerName", "BBC London")
      .addContent("en-US", "providerName", "CNN")
      .addContent("en-GB", "providerName", "BBC")
      .addContent("en-US", "subject", "Merry Christmas in Chicago")
      .addContent("en-GB", "subject", "Merry Christmas in London")
      .setReferenceId("referenceId1")
      .setTimestamp("2018-12-19T21:56:24.00Z")
      .setExpiryTime("2018-12-19T22:57:24.00Z")
      .setMulticast();

    nock(endpoint, { reqheaders })
      .post("/v1/proactiveEvents/stages/development", event.build())
      .reply(200);

    const proactiveEvents = new ProactiveEvents(clientId, clientSecret);
    const messageResponse = await proactiveEvents.createEvent(endpoint, event, true);

    expect(messageResponse).to.be.undefined;
  });

  it("should get a new access token and send a TrashCollectionAlert event", async () => {
    reqheaders = {
      "accept": "application/json",
      "authorization": `Bearer ${tokenResponse.access_token}`,
      "content-length": 348,
      "content-type": "application/json",
      "host": "api.amazonalexa.com",
    };

    const userId = "userId";
    const endpoint: string = "https://api.amazonalexa.com";

    const event: TrashCollectionAlertEventBuilder = new TrashCollectionAlertEventBuilder();
    event
      .setAlert(GARBAGE_COLLECTION_DAY.MONDAY,
        GARBAGE_TYPE.BOTTLES,
        GARBAGE_TYPE.BULKY,
        GARBAGE_TYPE.CANS,
        GARBAGE_TYPE.CLOTHING)
      .setReferenceId("referenceId1")
      .setTimestamp("2018-12-19T21:56:24.00Z")
      .setExpiryTime("2018-12-19T22:57:24.00Z")
      .setMulticast();

    nock(endpoint, { reqheaders })
      .post("/v1/proactiveEvents/stages/development", event.build())
      .reply(200);

    const proactiveEvents = new ProactiveEvents(clientId, clientSecret);
    const messageResponse = await proactiveEvents.createEvent(endpoint, event, true);

    expect(messageResponse).to.be.undefined;
  });

  it("should get a new access token and send a MediaContent event", async () => {
    reqheaders = {
      "accept": "application/json",
      "authorization": `Bearer ${tokenResponse.access_token}`,
      "content-length": 568,
      "content-type": "application/json",
      "host": "api.amazonalexa.com",
    };

    const userId = "userId";
    const endpoint: string = "https://api.amazonalexa.com";

    const event: MediaContentEventBuilder = new MediaContentEventBuilder();
    event
      .setAvailability(MEDIA_CONTENT_METHOD.AIR)
      .setContentType(MEDIA_CONTENT_TYPE.ALBUM)
      .addContent("en-US", "providerName", "CNN")
      .addContent("en-GB", "providerName", "BBC")
      .addContent("en-US", "contentName", "News")
      .addContent("en-GB", "contentName", "Alerts")
      .setReferenceId("referenceId1")
      .setTimestamp("2018-12-19T21:56:24.00Z")
      .setExpiryTime("2018-12-19T22:57:24.00Z")
      .setMulticast();

    nock(endpoint, { reqheaders })
      .post("/v1/proactiveEvents/stages/development", event.build())
      .reply(200);

    const proactiveEvents = new ProactiveEvents(clientId, clientSecret);
    const messageResponse = await proactiveEvents.createEvent(endpoint, event, true);

    expect(messageResponse).to.be.undefined;
  });

  it("should get a new access token and send a SocialGameInvite event", async () => {
    reqheaders = {
      "accept": "application/json",
      "authorization": `Bearer ${tokenResponse.access_token}`,
      "content-length": 478,
      "content-type": "application/json",
      "host": "api.amazonalexa.com",
    };

    const userId = "userId";
    const endpoint: string = "https://api.amazonalexa.com";

    const event: SocialGameInviteEventBuilder = new SocialGameInviteEventBuilder();
    event
      .setGame(SOCIAL_GAME_OFFER.GAME)
      .setInvite("Test", SOCIAL_GAME_INVITE_TYPE.CHALLENGE, SOCIAL_GAME_RELATIONSHIP_TO_INVITEE.CONTACT)
      .addContent("en-US", "gameName", "CNN")
      .addContent("en-GB", "gameName", "BBC")
      .setReferenceId("referenceId1")
      .setTimestamp("2018-12-19T21:56:24.00Z")
      .setExpiryTime("2018-12-19T22:57:24.00Z")
      .setMulticast();

    nock(endpoint, { reqheaders })
      .post("/v1/proactiveEvents/stages/development", event.build())
      .reply(200);

    const proactiveEvents = new ProactiveEvents(clientId, clientSecret);
    const messageResponse = await proactiveEvents.createEvent(endpoint, event, true);

    expect(messageResponse).to.be.undefined;
  });

  it("should get a new access token and send a general/custom event", async () => {
    reqheaders = {
      "accept": "application/json",
      "authorization": `Bearer ${tokenResponse.access_token}`,
      "content-length": 328,
      "content-type": "application/json",
      "host": "api.amazonalexa.com",
    };

    const userId = "userId";
    const endpoint: string = "https://api.amazonalexa.com";

    const event: EventBuilder = new EventBuilder("MyCustomEvent");
    event
      .addContent("en-US", "source", "CNN")
      .addContent("en-GB", "source", "BBC")
      .setPayload({ customProperty: "customValue" })
      .setReferenceId("referenceId1")
      .setTimestamp("2018-12-19T21:56:24.00Z")
      .setExpiryTime("2018-12-19T22:57:24.00Z")
      .setMulticast();

    nock(endpoint, { reqheaders })
      .post("/v1/proactiveEvents/stages/development", event.build())
      .reply(200);

    const proactiveEvents = new ProactiveEvents(clientId, clientSecret);
    const messageResponse = await proactiveEvents.createEvent(endpoint, event, true);

    expect(messageResponse).to.be.undefined;
  });
});


text:
package auth

import (
	"io/ioutil"
	"os"
	"strings"
	"testing"

	logging "github.com/op/go-logging"
	ft "github.com/openshift/ansible-service-broker/pkg/fusortest"
)

var log = logging.MustGetLogger("auth")

func TestNewFusa(t *testing.T) {
	username := []byte("admin")
	password := []byte("admin")
	ioutil.WriteFile("/tmp/username", username, 0644)
	ioutil.WriteFile("/tmp/password", password, 0644)

	defer os.Remove("/tmp/username")
	defer os.Remove("/tmp/password")

	fusa, err := NewFileUserServiceAdapter("/tmp/", log)
	if err != nil {
		t.Fatal(err.Error())
	}
	adminuser, _ := fusa.FindByLogin("admin")
	ft.AssertEqual(t, adminuser.Username, "admin", "username does not match")
	ft.AssertEqual(t, adminuser.Password, "admin", "password does not match")
	ft.AssertTrue(t, fusa.ValidateUser("admin", "admin"), "validation failed")
	ft.AssertFalse(t, fusa.ValidateUser("notme", "admin"), "validation passed, expected failure")
	ft.AssertFalse(t, fusa.ValidateUser("", ""), "expected failure on empty string")
}

func TestErrorBuild(t *testing.T) {
	fusa, err := NewFileUserServiceAdapter("", log)
	if fusa != nil {
		t.Fatal("fusa is not nil")
	}
	ft.AssertNotNil(t, err, "expected an error")
	ft.AssertTrue(t, strings.Contains(err.Error(), "directory is empty,"))
}

func TestFusaError(t *testing.T) {
	_, err := NewFileUserServiceAdapter("/var/tmp", log)
	ft.AssertNotNil(t, err, "should have gotten an error")
	ft.AssertTrue(t, strings.Contains(err.Error(), "no such file or directory"), "mismatch error message")
}

func TestUser(t *testing.T) {
	user := User{Username: "admin", Password: "password"}
	ft.AssertEqual(t, user.GetType(), "user", "type doesn't match user")
	ft.AssertEqual(t, user.GetName(), user.Username, "get name and username do not match")
}


text:
import * as plugins from './mod.plugins';
import * as paths from '../gitzone.paths';
import * as legal from '@umbrellazone/legal';

export const run = async () => {
  const licenseChecker = await legal.createLicenseChecker();
  let licenseCheckResult = await licenseChecker.excludeLicenseWithinPath(paths.cwd, []);
  if (licenseCheckResult.failingModules.length === 0) {
    plugins.smartlog.defaultLogger.info('Success -> licenses passed!');
  } else {
    plugins.smartlog.defaultLogger.error('Error -> licenses failed. Here is why:');
    for (let failedModule of licenseCheckResult.failingModules) {
      console.log(`${failedModule.moduleName} fails with license ${failedModule.license}`);
    }
  }
};


text:
"""
Django settings for demo project.

For more information on this file, see
https://docs.djangoproject.com/en/1.7/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.7/ref/settings/
"""
import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(__file__))

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '*p_&!3^v6@n_&wy7l_ewpe3e-6cxg@qa-38hw9uu=k=w7f'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

TEMPLATE_DEBUG = True

ALLOWED_HOSTS = []

# Application definition
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django_extensions',
    'rest_framework',
    'autores',
    'libros',
    'angular',
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'demo.urls'

WSGI_APPLICATION = 'demo.wsgi.application'

# Database
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

# Internationalization
# https://docs.djangoproject.com/en/1.7/topics/i18n/
LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.7/howto/static-files/
STATIC_URL = '/assets/'

STATICFILES_DIRS = (
    os.path.realpath(os.path.join(BASE_DIR, '..', 'assets')),
)

STATIC_ROOT = os.path.realpath(
    os.path.join(BASE_DIR, '..', '..', 'media', 'assets')
)

# Template directories
# See https://docs.djangoproject.com/en/1.7/ref/settings/#template-dirs
TEMPLATE_DIRS = (
    os.path.realpath(os.path.join(BASE_DIR, '..', 'templates')),
)

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),
}


text:
package app

import (
	"github.com/codegangsta/cli"
	"github.com/docker/libcompose/command"
	"github.com/docker/libcompose/project"
	"github.com/rancherio/rancher-compose/rancher"
)

type ProjectFactory struct {
}

func (p *ProjectFactory) Create(c *cli.Context) (*project.Project, error) {
	context := &rancher.Context{
		RancherComposeFile: c.GlobalString("rancher-file"),
		Url:                c.GlobalString("url"),
		AccessKey:          c.GlobalString("access-key"),
		SecretKey:          c.GlobalString("secret-key"),
	}
	command.Populate(&context.Context, c)

	return rancher.NewProject(context)
}


text:
package com.haulmont.cuba.security.app.group;

import com.haulmont.cuba.security.group.AccessGroupDefinition;
import com.haulmont.cuba.security.group.ConstraintsContainer;

import javax.inject.Inject;
import java.io.Serializable;
import java.util.Map;

public abstract class AnnotatedAccessGroupDefinition implements AccessGroupDefinition {
    @Inject
    protected AnnotatedGroupDefinitionBuilder annotatedGroupDefinitionBuilder;

    @Override
    public String getName() {
        return annotatedGroupDefinitionBuilder.getNameFromAnnotation(this);
    }

    @Override
    public String getParent() {
        return annotatedGroupDefinitionBuilder.getParentFromAnnotation(this);
    }

    @Override
    public ConstraintsContainer accessConstraints() {
        return annotatedGroupDefinitionBuilder.buildSetOfAccessConstraints(this);
    }

    @Override
    public Map<String, Serializable> sessionAttributes() {
        return annotatedGroupDefinitionBuilder.buildSessionAttributes(this);
    }
}


text:
ACCEPTED

#### According to
Index Fungorum

#### Published in
null

#### Original name
Sphaerella nigrificata Fautrey

### Remarks
null


text:
namespace ExRam.Gremlinq.Core.ExpressionParsing
{
    internal enum WellKnownMember
    {
        Equals,

        PropertyValue,
        PropertyKey,
        StepLabelValue,
        VertexPropertyLabel,

        EnumerableIntersectAny,
        EnumerableAny,
        EnumerableContains,

        ListContains,

        StringEquals,
        StringContains,
        StringStartsWith,
        StringEndsWith,

        ComparableCompareTo,

        ArrayLength
    }
}


text:
/**
 *
 */
package od;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import od.exception.MissingCookieException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AuthorizationServiceException;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

/**
 * @author ggilbert
 *
 */
@Component
public class ExceptionFilter extends OncePerRequestFilter {
  private static final Logger logger = LoggerFactory.getLogger(ExceptionFilter.class);

  @Override
  protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain fc) throws ServletException, IOException {
    logger.debug("In ExceptionFilter");

    try {
      fc.doFilter(req, res);

      // handle exceptions thrown by downstream filters
      // catch exception type / set appropriate http status code
      // and error message key
      // ultimately these responses are handled by
      // https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/BasicErrorController.java
      // the response varies based on the content type of the request (i.e., text/html will return the /error.html page, otherwise a json response is returned)
    }
    catch (MissingCookieException missingCookieException) {
      // getting a little creative with the status code here
      // want to distiguish from unauthorized
      res.sendError(HttpStatus.NOT_ACCEPTABLE.value(), "COOKIE_ERROR");
    }
    catch (AuthorizationServiceException authorizationServiceException) {
      res.sendError(HttpStatus.UNAUTHORIZED.value(), "AUTHORIZATION_ERROR");
    }
    catch(Throwable t) {
      res.sendError(HttpStatus.INTERNAL_SERVER_ERROR.value(), "GENERAL_ERROR");
    }

  }

}


text:
var squel = require( "squel" ),
    expect = require( "chai" ).expect,
    inaturalist = require( "../lib/inaturalist" ),
    config = require("../config"),
    req, query,
    emptyRequest = { inat: { }, params: { } };

var assertError = function( err ) {
  expect( err ).to.include( "[ERROR]" );
};

var assertDebug = function( debug ) {
  expect( debug ).to.include( "[DEBUG]" );
};

inaturalist.setErrorCallback( assertError );
inaturalist.setDebugCallback( assertDebug );

describe( "inaturalist", function( ) {

  describe( "connect", function( ) {
    it( "connects to the DB and assigns pgClient", function( done ) {
      expect( inaturalist.pgClient ).to.be.null;
      inaturalist.connect( function( ) {
        expect( inaturalist.pgClient ).to.not.be.null;
        done( );
      });
    });
  });

  describe( "startServer", function( ) {
    it( "starts the server", function( done ) {
      inaturalist.startServer( function( ) {
        done( );
      });
    });
  });

  describe( "loadTaxon", function( ) {
    it( "loads a taxon from the database", function( done ) {
      var req = { inat: { }, params: { taxon_id: 1 } };
      expect( req.inat.taxon ).to.be.undefined;
      inaturalist.loadTaxon( req, function( ) {
        expect( req.inat.taxon ).to.not.be.null;
        expect( req.inat.taxon.id ).to.equal( 1 );
        expect( req.inat.taxon.name ).to.equal( "Animalia" );
        expect( req.inat.taxon.rank ).to.equal( "kingdom" );
        done( );
      });
    });

    it( "throws an error when a query fails", function( done ) {
      var req = { inat: { }, params: { taxon_id: 'abcd' } };
      expect( req.inat.taxon ).to.be.undefined;
      inaturalist.loadTaxon( req, function( ) {
        expect( req.inat.taxon ).to.be.undefined;
        done( );
      });
    });
  });

  describe( "gridRequest", function( ) {
    beforeEach( function( ) {
      req = { inat: { cacheTable: "CT" }, params: { taxon_id: 1 } };
    });

    it( "creates the most basic grid query", function( done ) {
      expect( req.params.sql ).to.be.undefined;
      expect( req.params.style ).to.be.undefined;
      inaturalist.gridRequest( req, function( ) {
        expect( req.params.sql ).to.equal(
          "(SELECT count, geom FROM CT WHERE (taxon_id = 1)) AS snap_grid" );
        expect( req.params.style ).to.include( "[count>=45]" );
        done( );
      });
    });

    it( "filters by user", function( done ) {
      req.params.user_id = 1;
      inaturalist.gridRequest( req, function( ) {
        expect( req.params.sql ).to.include(
          "INNER JOIN users u ON (o.user_id = u.id)" );
        expect( req.params.sql ).to.include( "AND (u.id = 1)" );
        done( );
      });
    });

    it( "bases grid opacity on maximum count", function( done ) {
      req.inat.maximumCount = 1000;
      inaturalist.gridRequest( req, function( ) {
        expect( req.params.style ).to.include(
          "[count<=2000] { polygon-fill: #6E6E6E; polygon-opacity:1; }" );
        expect( req.params.style ).to.include(
          "[count<2] { polygon-fill: #6E6E6E; polygon-opacity:0.28; }" );
        done( );
      });
    });

    it( "sets the color based on parameter", function( done ) {
      req.params.color = "#ABCDEF";
      expect( req.params.style ).to.not.include( "#ABCDEF" );
      inaturalist.gridRequest( req, function( ) {
        expect( req.params.style ).to.include( "#ABCDEF" );
        done( );
      });
    });

    it( "fails when Z is out of bounds", function( done ) {
      req.params.z = 13;
      inaturalist.gridRequest( req, function( err ) {
        expect( err ).to.equal( "Unable to process grid requests for this zoom level" );
        done( );
      });
    });
  });

  describe( "pointsRequest", function( ) {
    beforeEach( function( ) {
      req = { inat: { cacheTable: "CT" }, params: { taxon_id: 1 } };
    });

    it( "creates the most basic points query", function( done ) {
      expect( req.params.sql ).to.be.undefined;
      expect( req.params.style ).to.be.undefined;
      inaturalist.pointsRequest( req, function( ) {
        expect( req.params.sql ).to.equal(
          "(SELECT o.id, o.species_guess, o.iconic_taxon_id, o.taxon_id, " +
          "o.latitude, o.longitude, o.geom, o.positional_accuracy, " +
          "o.captive, o.quality_grade FROM observations o " +
          "WHERE (o.mappable = true) AND (o.private_latitude IS NULL) " +
          "AND (o.private_longitude IS NULL)) AS points" );
        expect( req.params.style ).to.include(
          "[iconic_taxon_id=47686] { marker-fill: #8B008B; }" );
        done( );
      });
    });

    it( "filters by observation", function( done ) {
      req.params.observation_id = "1";
      inaturalist.pointsRequest( req, function( ) {
        expect( req.params.sql ).to.include( "AND (o.id NOT IN (1))" );
        done( );
      });
    });

    it( "fails when Z is out of bounds", function( done ) {
      req.params.z = config.application.min_zoom_level_for_points - 1;
      inaturalist.pointsRequest( req, function( err ) {
        expect( err ).to.equal( "Unable to process point requests for this zoom level" );
        done( );
      });
    });

    it( "can set an overriding color", function( done ) {
      req.params.color = "#ABCDEF";
      inaturalist.pointsRequest( req, function( err ) {
        expect( req.params.style ).to.include(
          "[zoom >= 0] { marker-fill: #ABCDEF; }" );
        done( );
      });
    });
  });

  describe( "placeRequest", function( ) {
    beforeEach( function( ) {
      req = { params: { endpoint_or_id: 1, z: 1 } };
    });

    it( "can set an overriding color", function( done ) {
      req.params.color = "#ABCDEF";
      inaturalist.placeRequest( req, function( err ) {
        expect( req.params.style ).to.include(
          "#places {polygon-fill:#ABCDEF;" );
        done( );
      });
    });
  });

  describe( "taxonRangeRequest", function( ) {
    beforeEach( function( ) {
      req = { params: { endpoint_or_id: 1, z: 1 } };
    });

    it( "can set an overriding color", function( done ) {
      req.params.color = "#ABCDEF";
      inaturalist.taxonRangeRequest( req, function( err ) {
        expect( req.params.style ).to.include(
          "#taxon_ranges {polygon-fill:#ABCDEF;" );
        done( );
      });
    });
  });

  describe( "taxonPlacesRequest", function( ) {
    beforeEach( function( ) {
      req = { params: { endpoint_or_id: 1, z: 1 } };
    });

    it( "creates the most basic points query", function( done ) {
      expect( req.params.sql ).to.be.undefined;
      expect( req.params.style ).to.be.undefined;
      inaturalist.taxonPlacesRequest( req, function( ) {
        expect( req.params.sql ).to.equal( "(SELECT geom, " +
          "MAX(lt.last_observation_id) as last_observation_id, "+
          "MAX(lt.occurrence_status_level) as occurrence_status_level, " +
          "MAX(lt.establishment_means) as establishment_means FROM listed_taxa lt " +
          "INNER JOIN places p ON (lt.place_id = p.id) "+
          "INNER JOIN place_geometries pg ON (p.id = pg.place_id) "+
          "WHERE (lt.taxon_id = 1 and p.admin_level = 0) GROUP BY geom) AS places" );
        expect( req.params.style ).to.include( "#taxon_places" );
        done( );
      });
    });

    it( "sets admin_level based on zoom", function( done ) {
      req.params.z = 4;
      inaturalist.taxonPlacesRequest( req, function( err ) {
        expect( req.params.sql ).to.include( "admin_level = 1" );
        done( );
      });
    });

    it( "sets admin_level based on zoom", function( done ) {
      req.params.z = 6;
      inaturalist.taxonPlacesRequest( req, function( err ) {
        expect( req.params.sql ).to.include( "admin_level = 2" );
        done( );
      });
    });

    it( "sets admin_level based on zoom", function( done ) {
      req.params.z = 12;
      inaturalist.taxonPlacesRequest( req, function( err ) {
        expect( req.params.sql ).to.include( "admin_level = 3" );
        done( );
      });
    });

    it( "can set an overriding confirmed color", function( done ) {
      req.params.confirmed_color = "#ABCDEF";
      inaturalist.taxonPlacesRequest( req, function( err ) {
        expect( req.params.style ).to.include(
          "#taxon_places {polygon-fill:#DAA520;" );
        expect( req.params.style ).to.include(
          "[last_observation_id > 0] {   line-color:#ABCDEF;" );
        done( );
      });
    });

    it( "can set an overriding unconfirmed color", function( done ) {
      req.params.unconfirmed_color = "#ABCDEF";
      inaturalist.taxonPlacesRequest( req, function( err ) {
        expect( req.params.style ).to.include(
          "#taxon_places {polygon-fill:#ABCDEF;" );
        expect( req.params.style ).to.include(
          "[last_observation_id > 0] {   line-color:#088A08;" );
        done( );
      });
    });
  });

  describe( "lookupMaxCountForGrid", function( ) {
    beforeEach( function( ) {
      req = { inat: { cacheTable: "observation_zooms_2" }, params: { z: 1 } };
    });

    it( "looks up max counts with no filters", function( done ) {
      expect( req.inat.maximumCount ).to.be.undefined;
      inaturalist.lookupMaxCountForGrid( req, function( ) {
        expect( req.inat.maximumCount ).to.be.above( 150000 );
        done( );
      });
    });

    // this is a poor test. Hard to test if the value was fetched in
    // real-time or cached. But the code coverage report will show
    // the cache code being called. As long as we get the right value...
    it( "caches max counts", function( done ) {
      expect( req.inat.maximumCount ).to.be.undefined;
      inaturalist.lookupMaxCountForGrid( req, function( ) {
        inaturalist.lookupMaxCountForGrid( req, function( ) {
          expect( req.inat.maximumCount ).to.be.above( 150000 );
          done( );
        });
      });
    });

    it( "looks up max counts with a taxon filter", function( done ) {
      req.params.taxon_id = 1;
      expect( req.inat.maximumCount ).to.be.undefined;
      inaturalist.lookupMaxCountForGrid( req, function( ) {
        expect( req.inat.maximumCount ).to.be.below( 150000 );
        expect( req.inat.maximumCount ).to.be.above( 75000 );
        done( );
      });
    });

    it( "looks up max counts with a user filter", function( done ) {
      req.params.user_id = 1;
      expect( req.inat.maximumCount ).to.be.undefined;
      inaturalist.lookupMaxCountForGrid( req, function( ) {
        expect( req.inat.maximumCount ).to.be.below( 20000 );
        expect( req.inat.maximumCount ).to.be.above( 10000 );
        done( );
      });
    });

    it( "throws an error when the query fails", function( done ) {
      req.inat.cacheTable = "dummy_table";
      expect( req.inat.maximumCount ).to.be.undefined;
      inaturalist.lookupMaxCountForGrid( req, function( ) {
        expect( req.inat.maximumCount ).to.be.undefined;
        done( );
      });
    });
  });

  describe( "req2params", function( ) {
    beforeEach( function( ) {
      req = { params: { x: 1, y: 1, z: 1 } };
    });

    it( "runs a dummy query when there is no endpoint", function( done ) {
      inaturalist.req2params( req, function( ) {
        expect( req.params.sql ).to.equal(
          "(SELECT geom FROM observations WHERE 1 = 2) AS foo" );
        done( );
      });
    });

    it( "runs a dummy query when there is a wrong endpoint", function( done ) {
      req.params.table = "observations";
      req.params.endpoint_or_id = "somethingOtherThanGridOrPoints";
      inaturalist.req2params( req, function( ) {
        expect( req.params.sql ).to.equal(
          "(SELECT geom FROM observations WHERE 1 = 2) AS foo" );
        done( );
      });
    });

    it( "passes off to the grid endpoint", function( done ) {
      req.params.table = "observations";
      req.params.endpoint_or_id = "grid";
      inaturalist.req2params( req, function( ) {
        expect( req.params.sql ).to.equal(
          "(SELECT count, geom FROM observation_zooms_2 WHERE (taxon_id IS NULL)) AS snap_grid" );
        done( );
      });
    });

    it( "filters by taxon", function( done ) {
      req.params.table = "observations";
      req.params.endpoint_or_id = "grid";
      req.params.taxon_id = 1;
      inaturalist.req2params( req, function( ) {
        expect( req.params.sql ).to.equal(
          "(SELECT count, geom FROM observation_zooms_2 WHERE (taxon_id = 1)) AS snap_grid" );
        done( );
      });
    });

    it( "still filters by taxon when debug mode is enabled", function( done ) {
      inaturalist.setDebug( true );
      req.params.table = "observations";
      req.params.endpoint_or_id = "grid";
      req.params.taxon_id = 1;
      inaturalist.req2params( req, function( ) {
        expect( req.params.sql ).to.equal(
          "(SELECT count, geom FROM observation_zooms_2 WHERE (taxon_id = 1)) AS snap_grid" );
        done( );
      });
    });

    it( "passes off to the points endpoint", function( done ) {
      req.params.z = 12;
      req.params.table = "observations";
      req.params.endpoint_or_id = "points";
      inaturalist.req2params( req, function( ) {
        expect( req.params.sql ).to.include( "AS points" );
        done( );
      });
    });

    it( "passes off to the places endpoint", function( done ) {
      req.params.z = 12;
      req.params.table = "places";
      req.params.endpoint_or_id = 1;
      inaturalist.req2params( req, function( ) {
        expect( req.params.sql ).to.equal(
          "(SELECT geom FROM place_geometries WHERE (place_id=1)) AS places" );
        done( );
      });
    });

    it( "passes off to the taxon_ranges endpoint", function( done ) {
      req.params.z = 12;
      req.params.table = "taxon_ranges";
      req.params.endpoint_or_id = 1;
      inaturalist.req2params( req, function( ) {
        expect( req.params.sql ).to.equal(
          "(SELECT geom FROM taxon_ranges WHERE (taxon_id=1)) AS taxon_range" );
        done( );
      });
    });

    it( "passes off to the taxon_placesf endpoint", function( done ) {
      req.params.z = 1;
      req.params.table = "taxon_places";
      req.params.endpoint_or_id = 1;
      inaturalist.req2params( req, function( ) {
        expect( req.params.sql ).to.equal( "(SELECT geom, " +
          "MAX(lt.last_observation_id) as last_observation_id, "+
          "MAX(lt.occurrence_status_level) as occurrence_status_level, " +
          "MAX(lt.establishment_means) as establishment_means FROM listed_taxa lt " +
          "INNER JOIN places p ON (lt.place_id = p.id) "+
          "INNER JOIN place_geometries pg ON (p.id = pg.place_id) "+
          "WHERE (lt.taxon_id = 1 and p.admin_level = 0) GROUP BY geom) AS places" );
        done( );
      });
    });
  });

  describe( "finalizeRequest", function( ) {
    beforeEach( function( ) {
      req = { params: { x: 1, y: 1, z: 3 } };
    });

    it( "only modified coordinates if necessary", function( ) {
      inaturalist.finalizeRequest( null, req );
      expect( req.params.x ).to.equal( "1" );
      expect( req.params.y ).to.equal( "1" );
      expect( req.params.z ).to.equal( "3" );
    });

    it( "mods X coordinate when too high", function( ) {
      req.params.x = 10;
      inaturalist.finalizeRequest( null, req );
      expect( req.params.x ).to.equal( "2" );
    });

    it( "updates X coordinate when too low", function( ) {
      req.params.x = -20;
      inaturalist.finalizeRequest( null, req );
      expect( req.params.x ).to.equal( "5" );
    });

    it( "updates Y coordinate when too low", function( ) {
      req.params.y = -2;
      inaturalist.finalizeRequest( null, req );
      expect( req.params.y ).to.equal( "5" );
    });

    // this isn't a great test. We want to test an error is thrown, which means
    // calling assertDebug. You can really only find out in the code coverage
    // report. We can however confirm the integer 1 doesn't get turned into a string
    it( "throws an error when there is one", function( ) {
      expect( req.params.x ).to.equal( 1 );
      inaturalist.finalizeRequest( "err", req );
      expect( req.params.x ).to.equal( 1 );
    });
  });

  describe( "requestSeed", function( ) {
    it( "creates the right seeds", function( ) {
      expect( inaturalist.requestSeed( { params: { z: 0 } } )).to.equal( 4 );
      expect( inaturalist.requestSeed( { params: { z: 1 } } )).to.equal( 4 );
      expect( inaturalist.requestSeed( { params: { z: 2 } } )).to.equal( 4 );
      expect( inaturalist.requestSeed( { params: { z: 3 } } )).to.equal( 2 );
      // this is really the only tricky one
      expect( inaturalist.requestSeed( { params: { z: 4 } } )).to.equal( 0.99 );
      expect( inaturalist.requestSeed( { params: { z: 5 } } )).to.equal( 0.5 );
      expect( inaturalist.requestSeed( { params: { z: 6 } } )).to.equal( 0.25 );
      expect( inaturalist.requestSeed( { params: { z: 7 } } )).to.equal( 0.125 );
      expect( inaturalist.requestSeed( { params: { z: 8 } } )).to.equal( 0.0625 );
    });
  });

  describe( "filters", function( ) {
    beforeEach( function( ) {
      req = {
        inat: { taxon: { id: 1 } },
        params: { taxon_id: 1, user_id: 1, project_id: 1, place_id: 1 }
      };
      query = squel.select( ).from( "observations o" );
    });

    describe( "addTaxonFilter", function( ) {
      it( "adds a filter when there is a taxon", function( ) {
        inaturalist.addTaxonFilter( query, req );
        expect( query.toString( ) ).to.include(
          "INNER JOIN taxon_ancestors ta ON (ta.taxon_id = o.taxon_id) " +
          "WHERE (ta.ancestor_taxon_id = 1)" );
      });

      it( "does not add a filter filter when there is no taxon", function( ) {
        inaturalist.addTaxonFilter( query, emptyRequest );
        expect( query.toString( ) ).to.not.include(
          "INNER JOIN taxon_ancestors ta ON (ta.taxon_id = o.taxon_id) " +
          "WHERE (ta.ancestor_taxon_id = 1)" );
      });
    });

    describe( "addUserFilter", function( ) {
      it( "adds a filter when there is a user", function( ) {
        inaturalist.addUserFilter( query, req );
        expect( query.toString( ) ).to.include(
          "INNER JOIN users u ON (o.user_id = u.id) WHERE (u.id = 1)" );
      });

      it( "does not add a filter filter when there is no user", function( ) {
        inaturalist.addUserFilter( query, emptyRequest );
        expect( query.toString( ) ).to.not.include(
          "INNER JOIN users u ON (o.user_id = u.id) WHERE (u.id = 1)" );
      });
    });

    describe( "addPlaceFilter", function( ) {
      it( "adds a filter when there is a place", function( ) {
        inaturalist.addPlaceFilter( query, req );
        expect( query.toString( ) ).to.include(
          "INNER JOIN place_geometries pg ON " +
          "((ST_Intersects(pg.geom, o.private_geom))) WHERE (pg.place_id = 1)" );
      });

      it( "does not add a filter filter when there is no place", function( ) {
        inaturalist.addPlaceFilter( query, emptyRequest );
        expect( query.toString( ) ).to.not.include(
          "INNER JOIN place_geometries pg ON " +
          "((ST_Intersects(pg.geom, o.private_geom))) WHERE (pg.place_id = 1)" );
      });
    });

    describe( "addProjectFilter", function( ) {
      it( "adds a filter when there is a project", function( ) {
        inaturalist.addProjectFilter( query, req );
        expect( query.toString( ) ).to.include(
          "INNER JOIN project_observations po ON (o.id = po.observation_id) " +
          "WHERE (po.project_id = 1)" );
      });

      it( "does not add a filter filter when there is no project", function( ) {
        inaturalist.addProjectFilter( query, emptyRequest );
        expect( query.toString( ) ).to.not.include(
          "INNER JOIN project_observations po ON (o.id = po.observation_id) " +
          "WHERE (po.project_id = 1)" );
      });
    });

    describe( "addTaxonCondition", function( ) {
      it( "adds a condition when there is a taxon", function( ) {
        inaturalist.addTaxonCondition( query, req );
        expect( query.toString( ) ).to.include(
          "WHERE (taxon_id = 1)" );
      });

      it( "add a NULL condition when there is no taxon", function( ) {
        inaturalist.addTaxonCondition( query, emptyRequest );
        expect( query.toString( ) ).to.include(
          "WHERE (taxon_id IS NULL)" );
      });
    });
  });

  describe( "stylesFromMaxCount", function( ) {
    it( "creates the right styles for a maximum value", function( ) {
      var styles = inaturalist.stylesFromMaxCount( "10000" );
      expect( styles ).to.equal(
        "[count<=20000] { polygon-fill: {{color}}; polygon-opacity:1; } " +
        "[count<3981] { polygon-fill: {{color}}; polygon-opacity:0.92; } " +
        "[count<1585] { polygon-fill: {{color}}; polygon-opacity:0.84; } " +
        "[count<631] { polygon-fill: {{color}}; polygon-opacity:0.76; } " +
        "[count<251] { polygon-fill: {{color}}; polygon-opacity:0.68; } " +
        "[count<100] { polygon-fill: {{color}}; polygon-opacity:0.6; } " +
        "[count<40] { polygon-fill: {{color}}; polygon-opacity:0.52; } " +
        "[count<16] { polygon-fill: {{color}}; polygon-opacity:0.44; } " +
        "[count<6] { polygon-fill: {{color}}; polygon-opacity:0.36; } " +
        "[count<3] { polygon-fill: {{color}}; polygon-opacity:0.28; } " );
    });

    it( "adjusts styles for other opacities", function( ) {
      var styles = inaturalist.stylesFromMaxCount( "10000", 0.5 );
      expect( styles ).to.equal(
        "[count<=20000] { polygon-fill: {{color}}; polygon-opacity:0.5; } " +
        "[count<3981] { polygon-fill: {{color}}; polygon-opacity:0.46; } " +
        "[count<1585] { polygon-fill: {{color}}; polygon-opacity:0.42; } " +
        "[count<631] { polygon-fill: {{color}}; polygon-opacity:0.38; } " +
        "[count<251] { polygon-fill: {{color}}; polygon-opacity:0.34; } " +
        "[count<100] { polygon-fill: {{color}}; polygon-opacity:0.3; } " +
        "[count<40] { polygon-fill: {{color}}; polygon-opacity:0.26; } " +
        "[count<16] { polygon-fill: {{color}}; polygon-opacity:0.22; } " +
        "[count<6] { polygon-fill: {{color}}; polygon-opacity:0.18; } " +
        "[count<3] { polygon-fill: {{color}}; polygon-opacity:0.14; } " );
    });
  });

  describe( "beforeTileRender", function( ) {
    it( "just calls a callback with null", function( done ) {
      inaturalist.beforeTileRender( { }, " ", function( val ) {
        expect( val ).to.be.null;
        done( );
      });
    });
  });

  describe( "afterTileRender", function( ) {
    it( "sets a default header", function( done ) {
      var req = { params: { } };
      inaturalist.afterTileRender( req, " ", " ", { }, function( val, t, h ) {
        expect( h["Cache-Control"] ).to.equal( "public, max-age=" + (60 * 60) );
        done( );
      });
    });

    it( "sets a default header for each endpoint", function( done ) {
      var req = { params: { endpoint: 'places' } };
      inaturalist.afterTileRender( req, " ", " ", { }, function( val, t, h ) {
        expect( h["Cache-Control"] ).to.equal( "public, max-age=" + (60 * 60 * 24 * 7) );
        done( );
      });
    });

    it( "allows a custom TTL", function( done ) {
      var req = { params: { ttl: 1234 } };
      inaturalist.afterTileRender( req, " ", " ", { }, function( val, t, h ) {
        expect( h["Cache-Control"] ).to.equal( "public, max-age=1234" );
        done( );
      });
    });
  });
});


text:
[![Build Status](https://travis-ci.org/vigetlabs/rails_polymorphic_select.png?branch=master)](https://travis-ci.org/vigetlabs/rails_polymorphic_select) [![Code Climate](https://codeclimate.com/github/vigetlabs/rails_polymorphic_select.png)](https://codeclimate.com/github/vigetlabs/rails_polymorphic_select)

This is a simple Rails extension that allows you to create polymorphic select inputs for relationships that are polymorphic.

## Install

Just add this to your `Gemfile` and then `bundle install`:

```ruby
gem 'rails_polymorphic_select'
```

## Usage

When using any `ActionView::Helpers::FormBuilder` object (either from the `form_for` helper method or a custom `FormBuilder` object) you can now call the method `polymorphic_select` like so:

```
<%= form.polymorphic_select :association_name_global_id, [News, Event, Photo] %>
```

The first argument it accepts is a method name (like all `FormBuilder` input methods), except you'll notice it's a `*_global_id` method. This library will automatically add these methods on all polymorphic relationships you create in your app. So if I have a `Tagging` model and I have a polymorphic relationship named `taggable` like this:

```ruby
class Tagging
  belongs_to :tag
  belongs_to :taggable, :polymorphic => true
end
```

This will create a `taggable_global_id` method and a `taggable_global_id=` method for reading and setting the taggable item by it's Global ID. However, it will not add these methods for non-polymorphic relationships (like `tag` in this case). Rails added [`GlobalID`](https://github.com/rails/globalid) functionality in 4.2, so now all ActiveRecord models have a `to_global_id` method that will return a `GlobalID` object that can be used to find the record.

The second argument `polymorphic_select` takes is an `Array` of `ActiveRecord` model classes that are valid options for this polymorphic relationship.

The third argument is an `options` argument and this gets passed to the [`FormBuilder#select`](http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select). Before that however there's one extra option that `polymorphic_select` accepts: `:label_method`. This is used as the method to call on individual records to get the value that users would see on the form select input for each record. By default it tries to find a good method (name, title, to_s, etc). If you prefer you can define a `to_label` or `display_name` method on the model(s), and these will be used.

The fourth argument is a `html_options` argument and this gets passed directly unaltered to [`FormBuilder#select`](http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select).

Worth noting is this greats a grouped selct input. So the records will be grouped by model class. The `polymorphic_select` method will use `ModelClass.model_name.human` to label the group. You can modify the name it supplies by manually editing the i18n value for the model.

### Advanced usage

Perhaps you have a `Tag` model with `taggings` but you want to access and set the individual `taggables`. In this case you could create your own `*_global_ids` methods and use this on with `polymorphic_select`. Say your `Tag` model looks like this:

```ruby
class Tag
  has_many :taggings

  def taggables
    taggings.map(&:taggable)
  end

  def taggable_global_ids
    taggables.map(&:to_global_id)
  end

  def taggalbe_global_ids=(global_ids)
    # your own code that at some point uses GlobalID::Locator.locate(global_id_value) to set the taggings
  end
end
```

Then in your form you could do:

```
<%= form.polymorphic_select :taggable_global_ids, [News, Event, Photo] %>
```

and it would just work!

## Contributing to RailsPolymorphicSelect

* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
* Fork the project.
* Start a feature/bugfix branch.
* Commit and push until you are happy with your contribution.
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.

## Copyright

Copyright (c) 2015 Brian Landau (Viget Labs). See MIT_LICENSE for further details.

***

Visit [code.viget.com](http://code.viget.com) to see more projects from [Viget.](https://viget.com)