text:
 Relations and Rules: building the evaluator
---------------------------------------------

While we could build a function which evaluates our programming languages, language designers love _natural deduction_ more. Don't worry if you never heard about that before, we'll explain it right away!

### Natural deduction

_Natural deduction_ is about defining __relations__. After declaring a relation, the elements that are part of the relation are defined by an __inference rule__, which looks like:

         Given predicates
	------------------ [Inference Rule Name]
	 Given conclusion

A conclusion would be, in our case, that certain elements are part of a relation.

This is Turing complete just as well. We yield this power to build the evaluator.

### Declaring evaluation

First, we declare a new section inside our _STFL.language_, with a relation declaration inside:

$$$STFL.language![60..63]!file

Let us break this line down.

The first part, `(→)`, says that we declare a relation with name `→`. Except from some builtin symbols, you can use whatever string you want, including unicode[^unicodeArrow]. If you don't want to use the unicode-arrow for this tutorial, you can replace `→` by `->`.

The second part, `: expr (in), expr (out)` states that this is a relation between two `expr`. As example, `2 + 3` , `5` will be in `(→)` or written more conventionally `2 + 3 →` `5`.

What about the `(in)` and `(out)` parts? These are called the __mode__ of the argument and are to help the computer. Given `2 + 3`, it's pretty easy for the computer to calculate `5`. Given `5`, the computer can't magically deduce that this was computed by calculating `2 + 3`, especially because an infinite amount of possible calculations lead to the result `5`.

The last part, `Pronounced as "evaluation"` defines a name for the relation. It's documentation, to help users of your language to know what a relation is supposed to do or to help them searching it on a search engine.

Note that the goal of `→` is to make a small, fundamental step - just one addition or simplification, e.g. `1 + 2 + 3` `→` `1 + 5`. We'll design another relation later on which will give us the end result immediatly, giving us `6`.

[^unicodeArrow]: to enter an unicode character on a linux machine, type `Left-Ctrl + Shift + U`, release, and type the hexcode of the desired character, e.g. `2192` to get the right-arrow. On windows, hold down `Alt` and type `+ 2192` (thus: type a plus, followed by typing the number).

### Defining evaluation

#### Simple deduction rules: If

Defining relations works with one or more rules.

We start with a simple one:

$$$STFLEvalIfCond.language![98..102]!file

How should you read this rule? The part under the line says that this is part of a relation, namley `→`; in other words; `"If" "True" "Then" e1 "Else" e2` will evaluate to `e1`.
This is equivalent to writing the function clause `eval("If" "True" "Then" e1 "Else" e2) = e1`.

The part right of the line (namely `[EvalIfTrue]`) gives the name of the rule. You can use whatever you want, it is documentation as well.

Analogously, you can add a rule for `If False`:

$$$STFLEvalIfCond.language![102..106]!file

This is already enough to run our third example. To run a relation, specify `-r <name-of-relation>`, thus `./ALGT STFL.language examples.stfl expr -l -r →`:

$$$($$$STFL.language![0..90],[104..112] $$$examples.stfl!3 expr -l -r → --nc)

#### Deduction rules with predicates: plus

How do we evaluate expressions with `+`? We can add a deduction rule for addition too:

$$$STFL.language![99..101]!file

First, take a look at the bottom line. The left part is straightforward; we match a parsetree with form `n1 + n2`. But what is `!plus(n1, n2)`? It's a function call with arguments `n1` and `n2`. The exclamation mark `!` indicates that this is a builtin function[^BuiltinFuncs].

[^BuiltinFuncs]: An overview for all builtin functions can be found in the [reference manual](#builtin-functions).

In other words, this rule indicates that `1 + 2` should be evaluated with `!plus(1,2)`, giving `3`.

There is a catch, though. `!plus` has type `Number -> Number -> Number` (recall, this means that plus takes two `Numbers` and gives us a `Number` in return).
We can't pass in other types, or it would fail. We thus have to check that we get correct input for this rule. To do this, we have those predicates on top: `n1:Number` and `n2:Number`. Read `n1:Number` as _`n1` is of syntactic form `Number`_.

Let give this a run!

$$$($$$STFL.language![0..90],[99..112] $$$examples.stfl!6,7 expr -l -r → --nc)

We can see that our simple example, `20 + 22` neatly gives us the answer[^tolife]. The other example, `1 + 2 + 3`, fails, giving a detailed overview of what rules it attempted to apply and why those rules failed.

[^tolife]: Luckily, your computer didn't have to run for 10 million years. And it conveniently gave the question too, so that we wouldn't forget it.

#### If with complicated conditions

But what with our fourth example, `$$$examples.stfl!4`? The condition itself as an `If`-expression as well.

Herefore we introduce a more complicated rule:

$$$STFLEvalIfCond.language![92..97]!file

This rule states that, whenever `cond0` evaluates to `cond1`, then we can evaluate the bigger expression.

We might also introduce two similar rules for, for evaluating the arguments of `+`, so that `1 + (2 + 3)` can be evaluated too. However, it is cumbersome to add all these extra rules for each syntactic form.

#### Evaluation contexts for congruence rules

Luckily, there is a way to write all those rules even shorter:

$$$STFL.language![92..97]!file

The part `expr[expr0]` will search, within the expression we want to evaluate, a nested expression that satisfies the conditions. In other words, it will search in the parsetree (e.g. `If (If True Then False Else False) Then True Else False`) a part that can be evaluated (e.g. `If True Then False Else False`). This part will be evaluated (to `False`) and plugged back in the bigger expression.

The evaluated expression will then be put back in the original, bigger parsetree at the same location.

Make sure to name the nested expr `expr0`, thus _syntactic-form-name_ followed by a number. That's how the tool figures out what kind of parsetree to search for.

$$$($$$STFL.language![0..112] $$$examples.stfl!4 expr -l -r → --nc --short-proofs 1)

As expected, this rule also solves our `1 + 2 + 3`!

$$$($$$STFL.language![0..112] $$$examples.stfl!7 expr -l -r → --nc)

These proofs are getting a bit harder to read. If you get lost, remember to always start from the bottom.

This proof states that `1 + (2 + 3)` makes a single step to `1 + 5`, because  of rule `EvalCtx`; this rule could be used because `2 + 3` evaluates to `5`.

The proof for that part of the evaluation is given on top, by rule `EvalPlus`, which could be invoked because both `2` and `3` are `Number`s.

#### Application

As last, we'd like to apply functions, such as `(\\x : Int . x + 1) 41`.

Our intution is that, given something as `(\\x : someType . someExpr) someArg`, we want to evaluate this to `someExpr`, where we replace every `x` in `someExpr`. Luckily, a builtin function does the hard part of replacing for us: `!subs`. This gives us the following rule:

$$$STFL.language!114,115!file

$$$($$$STFL.language![0..115] $$$examples.stfl!8 expr -l -r → --nc)

### Evaluation-relation: recap

Our evaluation rule is defined as:

$$$STFL.language![59..63],[86..88],[92..116]!file

### Is canonical

It is usefull to known when an expression is _canonical_, thus is fully evaluated. This can be simply stated by a relation taking just one argument and _giving no output_[^itsASet]. It should contain exactly the `Int`s, `True` and `False` (the `bool`s for short).

First, the declaration in the `Relations`-section:

$$$STFL.language!65!file

And the implementation in the `Rule`-section:

$$$STFL.language![120..127]!file

[^itsASet]: Mathematicians would call this a _set_.

### Bigstep

Of course, when we input `1 + 2 + 3`, we would like te get `6`, and not `1 + 5`. For this, we can define a third relation,

First, let us declare `bigstep`:

$$$STFL.language!64!file

The implementation is based on recursion. If something is canonical, we are done and just return the unchanged value.
We express this basecase as following:

$$$STFL.language![132..134]!file

What if we are not done? That means that we can make a single step, `e0 → e1` and that we calculate this `e1` to its canonical from `e2` with `bitstep` itself!

$$$STFL.language![136..138]!file

So, we finally did it! Time to see our examples in all their glory!

$$$($$$STFL.language![0..140] $$$examples.stfl!1 expr -l -r →* --nc)
$$$($$$STFL.language![0..140] $$$examples.stfl!2 expr -l -r →* --nc)
$$$($$$STFL.language![0..140] $$$examples.stfl!3 expr -l -r →* --short-proofs 4 --nc)

$$$($$$STFL.language![0..140] $$$examples.stfl!5 expr -l -r →* --nc)
$$$($$$STFL.language![0..140] $$$examples.stfl!6 expr -l -r →* --short-proofs 4 --nc)
$$$($$$STFL.language![0..140] $$$examples.stfl!7 expr -l -r →* --short-proofs 4 --nc)
$$$($$$STFL.language![0..140] $$$examples.stfl!8 expr -l -r →* --short-proofs 4 --nc)

redpajama_set_name: RedPajamaGithub


text:
conn SYS/xxxxxx@localhost/IA643 as sysdba;
Drop User sysadmin_ctx CASCADE;
CREATE USER sysadmin_ctx IDENTIFIED BY playboy;
GRANT CREATE SESSION, CREATE ANY CONTEXT, CREATE PROCEDURE, CREATE TRIGGER,
      ADMINISTER DATABASE TRIGGER TO sysadmin_ctx IDENTIFIED BY playboy;

GRANT EXECUTE ON DBMS_SESSION TO sysadmin_ctx;
GRANT EXECUTE ON DBMS_RLS TO sysadmin_ctx;
GRANT RESOURCE TO sysadmin_ctx;

conn DBA643/xxxxxx@localhost/IA643;
GRANT SELECT ON DBA643.Branch_Managers TO sysadmin_ctx;

--1.2 create context
conn sysadmin_ctx/playboy@localhost/IA643;
CREATE OR REPLACE CONTEXT MANAGER_CTX USING set_manager_ctx_pkg;

--1.3 create related procedure
CREATE OR REPLACE PACKAGE set_manager_ctx_pkg IS
   PROCEDURE get_branch_id;
 END;
 /
CREATE OR REPLACE PACKAGE BODY set_manager_ctx_pkg IS
   PROCEDURE get_branch_id
   IS
    branch_id_v NUMBER;
   BEGIN
    SELECT BRANCH_ID INTO branch_id_v FROM DBA643.Branch_Managers
       WHERE upper(SYSTEM_USERNAME) = upper(SYS_CONTEXT('USERENV', 'SESSION_USER'));
    DBMS_SESSION.SET_CONTEXT('MANAGER_CTX', 'BRANCH_ID_CTX', branch_id_v);
   EXCEPTION
    WHEN NO_DATA_FOUND THEN NULL;
  END;
 END;
/
show error;
--1.4 create related trigger
CREATE or Replace TRIGGER set_manager_ctx_trig AFTER LOGON ON DATABASE
 BEGIN
  sysadmin_ctx.set_manager_ctx_pkg.get_branch_id;
 END;
/
show error;
-- Step 2, Create policy
Create or Replace FUNCTION Sec_Fun_Cust (P_schema_name IN varchar2, P_object_name IN varchar2) Return varchar2 IS
  where_v varchar2(300);
BEGIN
  IF USER <> 'DBA643' then
    where_v := 'BRANCH_ID = ' || NVL(SYS_CONTEXT('MANAGER_CTX','BRANCH_ID_CTX'),0);
  ELSE
    where_v := '';
  END IF;
  return where_v;
END;
/
show error;

Create or Replace FUNCTION Sec_Fun_Cust1 (P_schema_name IN varchar2, P_object_name IN varchar2) Return varchar2 IS
  where_v varchar2(300);
BEGIN
  IF USER <> 'DBA643' then
     where_v := 'CTL_SEC_USER IN (SELECT UPPER(SYSTEM_USERNAME) FROM DBA643.Branch_Managers WHERE BRANCH_ID = '|| NVL(SYS_CONTEXT('MANAGER_CTX','BRANCH_ID_CTX'),0) || ')';
  ELSE
    where_v := '';
  END IF;
  return where_v;
END;
/
show error;

exec DBMS_RLS.DROP_Policy('DBA643', 'Branches', 'Row_Owner_Sec');
BEGIN
  DBMS_RLS.ADD_POLICY (object_schema     => 'DBA643',
                       object_name       => 'Branches',
                       policy_name       => 'Row_Owner_Sec',
                       function_schema   => 'sysadmin_ctx',
                       policy_function   => 'Sec_Fun_Cust',
                       statement_types   => 'SELECT, UPDATE, DELETE, INSERT',
                       update_check      => TRUE);
END;
/
exec DBMS_RLS.DROP_Policy('DBA643', 'Customers', 'Row_Owner_Sec');
exec DBMS_RLS.ADD_Policy ('DBA643','Customers','Row_Owner_Sec','sysadmin_ctx','Sec_Fun_Cust','SELECT, UPDATE, DELETE, INSERT',TRUE);
exec DBMS_RLS.DROP_Policy('DBA643', 'Financial_Products', 'Row_Owner_Sec1');
exec DBMS_RLS.ADD_Policy ('DBA643','Financial_Products','Row_Owner_Sec1','sysadmin_ctx','Sec_Fun_Cust1','SELECT, UPDATE, DELETE, INSERT',TRUE);
exec DBMS_RLS.DROP_Policy('DBA643', 'Transactions', 'Row_Owner_Sec1');
exec DBMS_RLS.ADD_Policy ('DBA643','Transactions','Row_Owner_Sec1','sysadmin_ctx','Sec_Fun_Cust1','SELECT, UPDATE, DELETE, INSERT',TRUE);

-- Step 3, Create another 2 users
conn DBA643/xxxxxx@localhost/IA643;
DROP USER PAdmin CASCADE;
Create User PAdmin identified by PAdmin
    DEFAULT TABLESPACE IA643_TBS
    TEMPORARY TABLESPACE TEMP
    ACCOUNT UNLOCK;

DROP USER KAdmin CASCADE;
Create User KAdmin identified by KAdmin
    DEFAULT TABLESPACE IA643_TBS
    TEMPORARY TABLESPACE TEMP
    ACCOUNT UNLOCK;
/
show error;
Grant Connect, Resource To PAdmin, KAdmin;

-- Step 4, create role and grant it to managers
Drop Role Manager_R;
Create Role Manager_R;
Grant SELECT, INSERT, UPDATE, DELETE ON Branches To Manager_R;
Grant SELECT, INSERT, UPDATE, DELETE ON Customers To Manager_R;
Grant SELECT, INSERT, UPDATE, DELETE ON Financial_Products To Manager_R;
Grant SELECT, INSERT, UPDATE, DELETE ON Transactions To Manager_R;

Grant Manager_R To BAdmin, CAdmin, PAdmin, KAdmin;
/
set serveroutput on;


text:
package com.ansorgit.plugins.bash.lang.psi.impl.arithmetic;

import com.ansorgit.plugins.bash.lang.psi.api.arithmetic.PostIncrementExpression;
import com.intellij.lang.ASTNode;
import com.intellij.psi.tree.IElementType;

/**
 * User: jansorg
 * Date: Feb 6, 2010
 * Time: 12:13:49 PM
 */
public class PostIncrementExpressionsImpl extends AbstractExpression implements PostIncrementExpression {
    public PostIncrementExpressionsImpl(final ASTNode astNode) {
        super(astNode, "ArithPostIncrement", Type.PostfixOperand);
    }

    @Override
    protected Long compute(long currentValue, IElementType operator, Long nextExpressionValue) {
        throw new UnsupportedOperationException("unsupported");
    }
}


text:
import os
from setuptools import setup

setup(
    name = "sgespawner",
    license = "BSD",
    packages=['sgespawner'],
    classifiers=[
        "Development Status :: 3 - Alpha",
        "Topic :: Utilities",
        "License :: OSI Approved :: BSD License",
    ],
)


text:
/**
 * TribeHR Custom Field Record
 * From: http://developers.tribehr.com/api/available-api-objects/users/
 *
 * A note on READONLY propeties:
 * All readonly properties will be stripped when record is saved and can only be set on User creation.
 */

var _ = require('underscore'),
    Record = require('./record');

module.exports = function(props) {

  this._READONLY = ''.split(', ');

  var properties = {
    id: null, // the ID of the this CustomFieldRecord entry
    custom_field_id: null, // the ID of the CustomField associated with this CustomFieldRecord
    user_id: null, // the ID of the User
    content: null // the value stored in the CustomFieldRecord (Text, optional)
  };

  var CustomFieldRecord = _.extend(Record(this, properties, props), {

  });

  return CustomFieldRecord;

};


text:
package org.wso2.carbon.apimgt.impl.kmclient;

import feign.Client;
import feign.Request;
import feign.Response;
import feign.Util;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.Configurable;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.wso2.carbon.apimgt.impl.APIConstants;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static feign.Util.UTF_8;

/***
 * This class is to be used to get HTTP Client from feign library
 * TODO: Remove this once the Http Client library is updated
 */
public final class ApacheFeignHttpClient implements Client {
    private static final String ACCEPT_HEADER_NAME = "Accept";

    private final HttpClient client;

    public ApacheFeignHttpClient() {
        this(HttpClientBuilder.create().build());
    }

    public ApacheFeignHttpClient(HttpClient client) {
        this.client = client;
    }

    @Override
    public Response execute(Request request, Request.Options options) throws IOException {
        HttpUriRequest httpUriRequest;
        try {
            httpUriRequest = toHttpUriRequest(request, options);
        } catch (URISyntaxException e) {
            throw new IOException("URL '" + request.url() + "' couldn't be parsed into a URI", e);
        }
        HttpResponse httpResponse = client.execute(httpUriRequest);
        return toFeignResponse(httpResponse, request);
    }

    HttpUriRequest toHttpUriRequest(Request request, Request.Options options)
            throws URISyntaxException {
        RequestBuilder requestBuilder = RequestBuilder.create(request.httpMethod().name());

        // per request timeouts
        RequestConfig requestConfig =
                (client instanceof Configurable ? RequestConfig.copy(((Configurable) client).getConfig())
                        : RequestConfig.custom())
                        .setConnectTimeout(options.connectTimeoutMillis())
                        .setSocketTimeout(options.readTimeoutMillis())
                        .build();
        requestBuilder.setConfig(requestConfig);

        URI uri = new URIBuilder(request.url()).build();

        requestBuilder.setUri(uri.getScheme() + "://" + uri.getAuthority() + uri.getRawPath());

        // request query params
        List<NameValuePair> queryParams =
                URLEncodedUtils.parse(uri, APIConstants.DigestAuthConstants.CHARSET);
        for (NameValuePair queryParam : queryParams) {
            requestBuilder.addParameter(queryParam);
        }

        // request headers
        boolean hasAcceptHeader = false;
        for (Map.Entry<String, Collection<String>> headerEntry : request.headers().entrySet()) {
            String headerName = headerEntry.getKey();
            if (headerName.equalsIgnoreCase(ACCEPT_HEADER_NAME)) {
                hasAcceptHeader = true;
            }

            if (headerName.equalsIgnoreCase(Util.CONTENT_LENGTH)) {
                // The 'Content-Length' header is always set by the Apache client and it
                // doesn't like us to set it as well.
                continue;
            }

            for (String headerValue : headerEntry.getValue()) {
                requestBuilder.addHeader(headerName, headerValue);
            }
        }
        // some servers choke on the default accept string, so we'll set it to anything
        if (!hasAcceptHeader) {
            requestBuilder.addHeader(ACCEPT_HEADER_NAME, "*/*");
        }

        // request body
        if (request.body() != null) {
            HttpEntity entity = null;
            if (request.charset() != null) {
                ContentType contentType = getContentType(request);
                String content = new String(request.body(), request.charset());
                entity = new StringEntity(content, contentType);
            } else {
                entity = new ByteArrayEntity(request.body());
            }

            requestBuilder.setEntity(entity);
        } else {
            requestBuilder.setEntity(new ByteArrayEntity(new byte[0]));
        }

        return requestBuilder.build();
    }

    private ContentType getContentType(Request request) {
        ContentType contentType = null;
        for (Map.Entry<String, Collection<String>> entry : request.headers().entrySet())
            if (entry.getKey().equalsIgnoreCase("Content-Type")) {
                Collection<String> values = entry.getValue();
                if (values != null && !values.isEmpty()) {
                    contentType = ContentType.parse(values.iterator().next());
                    if (contentType.getCharset() == null) {
                        contentType = contentType.withCharset(request.charset());
                    }
                    break;
                }
            }
        return contentType;
    }

    Response toFeignResponse(HttpResponse httpResponse, Request request) throws IOException {
        StatusLine statusLine = httpResponse.getStatusLine();
        int statusCode = statusLine.getStatusCode();

        String reason = statusLine.getReasonPhrase();

        Map<String, Collection<String>> headers = new HashMap<String, Collection<String>>();
        for (Header header : httpResponse.getAllHeaders()) {
            String name = header.getName();
            String value = header.getValue();

            Collection<String> headerValues = headers.get(name);
            if (headerValues == null) {
                headerValues = new ArrayList<String>();
                headers.put(name, headerValues);
            }
            headerValues.add(value);
        }

        return Response.builder()
                .status(statusCode)
                .reason(reason)
                .headers(headers)
                .request(request)
                .body(toFeignBody(httpResponse))
                .build();
    }

    Response.Body toFeignBody(HttpResponse httpResponse) {
        final HttpEntity entity = httpResponse.getEntity();
        if (entity == null) {
            return null;
        }
        return new Response.Body() {

            @Override
            public Integer length() {
                return entity.getContentLength() >= 0 && entity.getContentLength() <= Integer.MAX_VALUE
                        ? (int) entity.getContentLength()
                        : null;
            }

            @Override
            public boolean isRepeatable() {
                return entity.isRepeatable();
            }

            @Override
            public InputStream asInputStream() throws IOException {
                return entity.getContent();
            }

            @SuppressWarnings("deprecation")
            @Override
            public Reader asReader() throws IOException {
                return new InputStreamReader(asInputStream(), UTF_8);
            }

            @Override
            public Reader asReader(Charset charset) throws IOException {
                Util.checkNotNull(charset, "charset should not be null");
                return new InputStreamReader(asInputStream(), charset);
            }

            @Override
            public void close() throws IOException {
                EntityUtils.consume(entity);
            }
        };
    }
}


text:
using System;
using System.IO;
using PluginInterface;

namespace PluginApp
{
    public class Program
    {
        static void Main(string[] args)
        {
            //string pluginDir = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Plugins");
            var pluginDir = Path.GetFullPath(@"..\..\..\..\PluginLoader\ExamplePlugin\bin\Debug");

            var loader = new PluginCommon.PluginLoader(pluginDir);
            loader.PluginLoadComplete += PluginLoadComplete;
            loader.PluginLoadFailed += PluginLoadFailed;
            loader.PluginLoadingComplete += PluginLoadingComplete;
            loader.PluginLoadingStarted += PluginLoadingStarted;
            loader.GetPlugins();
            loader.InitialisePlugins(args);
            Console.ReadKey();
        }

        private static void PluginLoadingStarted(PluginCommon.PluginLoader sender, object otherData)
        {
            Console.WriteLine("Loading Started...");
        }

        private static void PluginLoadingComplete(PluginCommon.PluginLoader sender, object otherData)
        {
            Console.WriteLine("Loading Complete");
        }

        private static void PluginLoadFailed(PluginCommon.PluginLoader sender, object otherData)
        {
            Console.WriteLine("Load of plugin failed");
        }

        private static void PluginLoadComplete(PluginCommon.PluginLoader sender, object otherData)
        {
            Console.WriteLine("Load of plugin complete");
        }

        public static bool RegisterPlugin(dynamic plugin)
        {
            Console.WriteLine("Registering plugin...");
            if (plugin is IConsole)
            {
                var p = (IConsole) plugin;
                p.Run();
                return true;
            }
            Console.WriteLine("Failed");
            return false;
        }
    }
}


text:
package com.amazonaws.services.kendra.model;

import java.io.Serializable;
import javax.annotation.Generated;

import com.amazonaws.AmazonWebServiceRequest;

/**
 *
 * @see AWS API
 *      Documentation
 */
@Generated("com.amazonaws:aws-java-sdk-code-generator")
public class ClearQuerySuggestionsRequest extends com.amazonaws.AmazonWebServiceRequest implements Serializable, Cloneable {

    /**
     *

     * The identifier of the index you want to clear query suggestions from.
     *

     */
    private String indexId;

    /**
     *

     * The identifier of the index you want to clear query suggestions from.
     *

     *
     * @param indexId
     *        The identifier of the index you want to clear query suggestions from.
     */

    public void setIndexId(String indexId) {
        this.indexId = indexId;
    }

    /**
     *

     * The identifier of the index you want to clear query suggestions from.
     *

     *
     * @return The identifier of the index you want to clear query suggestions from.
     */

    public String getIndexId() {
        return this.indexId;
    }

    /**
     *

     * The identifier of the index you want to clear query suggestions from.
     *

     *
     * @param indexId
     *        The identifier of the index you want to clear query suggestions from.
     * @return Returns a reference to this object so that method calls can be chained together.
     */

    public ClearQuerySuggestionsRequest withIndexId(String indexId) {
        setIndexId(indexId);
        return this;
    }

    /**
     * Returns a string representation of this object. This is useful for testing and debugging. Sensitive data will be
     * redacted from this string using a placeholder value.
     *
     * @return A string representation of this object.
     *
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        if (getIndexId() != null)
            sb.append("IndexId: ").append(getIndexId());
        sb.append("}");
        return sb.toString();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;

        if (obj instanceof ClearQuerySuggestionsRequest == false)
            return false;
        ClearQuerySuggestionsRequest other = (ClearQuerySuggestionsRequest) obj;
        if (other.getIndexId() == null ^ this.getIndexId() == null)
            return false;
        if (other.getIndexId() != null && other.getIndexId().equals(this.getIndexId()) == false)
            return false;
        return true;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int hashCode = 1;

        hashCode = prime * hashCode + ((getIndexId() == null) ? 0 : getIndexId().hashCode());
        return hashCode;
    }

    @Override
    public ClearQuerySuggestionsRequest clone() {
        return (ClearQuerySuggestionsRequest) super.clone();
    }

}


text:
using Microsoft.Azure.Management.BatchAI.Fluent.Models;

namespace Microsoft.Azure.Management.BatchAI.Fluent
{
    using Microsoft.Azure.Management.BatchAI.Fluent.BatchAIJob.Definition;
    using Microsoft.Azure.Management.BatchAI.Fluent.ToolTypeSettings;
    using Microsoft.Azure.Management.BatchAI.Fluent.ToolTypeSettings.Caffe.Definition;
    using Microsoft.Azure.Management.BatchAI.Fluent.ToolTypeSettings.HasCommandLineArgs.Definition;
    using Microsoft.Azure.Management.BatchAI.Fluent.ToolTypeSettings.HasProcessCount.Definition;
    using Microsoft.Azure.Management.BatchAI.Fluent.ToolTypeSettings.HasPythonInterpreter.Definition;
    using Microsoft.Azure.Management.ResourceManager.Fluent.Core;

    /// <summary>
    /// Represents Caffe settings.
    /// </summary>
    public partial class CaffeImpl :
        IndexableWrapper<CaffeSettings>,
        ICaffe,
        IDefinition<BatchAIJob.Definition.IWithCreate>
    {
        private BatchAIJobImpl parent;
        internal CaffeImpl(CaffeSettings inner, BatchAIJobImpl parent)
            : base(inner)
        {
            this.parent = parent;
        }

        public CaffeImpl WithCommandLineArgs(string commandLineArgs)
        {
            Inner.CommandLineArgs = commandLineArgs;
            return this;
        }

        public CaffeImpl WithProcessCount(int processCount)
        {
            Inner.ProcessCount = processCount;
            return this;
        }

        public IWithCreate Attach()
        {
            this.parent.AttachCaffeSettings(this);
            return parent;
        }

        public CaffeImpl WithPythonInterpreterPath(string path)
        {
            Inner.PythonInterpreterPath = path;
            return this;
        }

        public CaffeImpl WithConfigFile(string configFilePath)
        {
            Inner.ConfigFilePath = configFilePath;
            return this;
        }

        public CaffeImpl WithPythonScriptFile(string pythonScriptFilePath)
        {
            Inner.PythonScriptFilePath = pythonScriptFilePath;
            return this;
        }
    }
}


text:
namespace frontlevel {

// Helper class that locks a mutex on construction and unlocks the mutex when
// the destructor of the MutexLock object is invoked.
//
// Typical usage:
//
//   void MyClass::MyMethod() {
//     MutexLock l(&mu_);       // mu_ is an instance variable
//     ... some complex code, possibly with multiple return paths ...
//   }

class SCOPED_LOCKABLE MutexLock {
 public:
  explicit MutexLock(port::Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu)
      : mu_(mu)  {
    this->mu_->Lock();
  }
  ~MutexLock() UNLOCK_FUNCTION() { this->mu_->Unlock(); }

 private:
  port::Mutex *const mu_;
  // No copying allowed
  MutexLock(const MutexLock&);
  void operator=(const MutexLock&);
};

}  // namespace frontlevel

#endif  // STORAGE_FRONTLEVEL_UTIL_MUTEXLOCK_H_


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using MyWeeFee.Models;

namespace MyWeeFee.Controllers
{
    public class TeachersController : Controller
    {
        private readonly MyWeeFeeContext _context;

        public TeachersController(MyWeeFeeContext context)
        {
            _context = context;
        }

        // GET: Teachers
        public async Task<IActionResult> Index()
        {
            return View(await _context.T_Teachers.ToListAsync());
        }

        // GET: Teachers/Details/5
        public async Task<IActionResult> Details(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var teacher = await _context.T_Teachers
                .SingleOrDefaultAsync(m => m.Id == id);
            if (teacher == null)
            {
                return NotFound();
            }

            return View(teacher);
        }

        // GET: Teachers/Create
        public IActionResult Create()
        {
            return View();
        }

        // POST: Teachers/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("Id,Email,Password,Firstname,Surename")] Teacher teacher)
        {
            if (ModelState.IsValid)
            {
                _context.Add(teacher);
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }
            return View(teacher);
        }

        // GET: Teachers/Edit/5
        public async Task<IActionResult> Edit(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var teacher = await _context.T_Teachers.SingleOrDefaultAsync(m => m.Id == id);
            if (teacher == null)
            {
                return NotFound();
            }
            return View(teacher);
        }

        // POST: Teachers/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, [Bind("Id,Email,Password,Firstname,Surename")] Teacher teacher)
        {
            if (id != teacher.Id)
            {
                return NotFound();
            }

            if (ModelState.IsValid)
            {
                try
                {
                    _context.Update(teacher);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!TeacherExists(teacher.Id))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
                return RedirectToAction(nameof(Index));
            }
            return View(teacher);
        }

        // GET: Teachers/Delete/5
        public async Task<IActionResult> Delete(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var teacher = await _context.T_Teachers
                .SingleOrDefaultAsync(m => m.Id == id);
            if (teacher == null)
            {
                return NotFound();
            }

            return View(teacher);
        }

        // POST: Teachers/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DeleteConfirmed(int id)
        {
            var teacher = await _context.T_Teachers.SingleOrDefaultAsync(m => m.Id == id);
            _context.T_Teachers.Remove(teacher);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }

        private bool TeacherExists(int id)
        {
            return _context.T_Teachers.Any(e => e.Id == id);
        }
    }
}


text:
/****************************************************************************************
Portions of this file are derived from the following 3GPP standard:

    3GPP TS 26.073
    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
    Available from http://www.3gpp.org

(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
Permission to distribute, modify and use this file under the standard license
terms listed above has been obtained from the copyright holder.
****************************************************************************************/
/*
------------------------------------------------------------------------------

 Filename: bgnscd.cpp
 Functions:
           Bgn_scd_reset
           Bgn_scd

------------------------------------------------------------------------------
 MODULE DESCRIPTION

 Background noise source characteristic detector (SCD)

------------------------------------------------------------------------------
*/

/*----------------------------------------------------------------------------
; INCLUDES
----------------------------------------------------------------------------*/
#include    "bgnscd.h"
#include    "typedef.h"
#include    "basic_op.h"
#include    "cnst.h"
#include    "gmed_n.h"
#include    "sqrt_l.h"
#include    "oscl_mem.h"

/*----------------------------------------------------------------------------
; MACROS
; Define module specific macros here
----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------
; DEFINES
; Include all pre-processor statements here. Include conditional
; compile variables also.
----------------------------------------------------------------------------*/
#define TRUE  1
#define FALSE 0

/*----------------------------------------------------------------------------
; LOCAL FUNCTION DEFINITIONS
; Function Prototype declaration
----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------
; LOCAL VARIABLE DEFINITIONS
; Variable declaration - defined here and used outside this module
----------------------------------------------------------------------------*/

/*
------------------------------------------------------------------------------
 FUNCTION NAME: Bgn_scd_reset
------------------------------------------------------------------------------
 INPUT AND OUTPUT DEFINITIONS

 Inputs:
    state = points to memory of type Bgn_scdState.

 Outputs:
    The memory of type Bgn_scdState pointed to by state is set to all
        zeros.

 Returns:
    Returns 0 if memory was successfully initialized,
        otherwise returns -1.

 Global Variables Used:
    None.

 Local Variables Needed:
    None.

------------------------------------------------------------------------------
 FUNCTION DESCRIPTION

 Resets state memory.

------------------------------------------------------------------------------
 REQUIREMENTS

 None

------------------------------------------------------------------------------
 REFERENCES

 bgnscd.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001

------------------------------------------------------------------------------
 PSEUDO-CODE

Word16 Bgn_scd_reset (Bgn_scdState *state)
{
   if (state == (Bgn_scdState *) NULL){
      fprintf(stderr, "Bgn_scd_reset: invalid parameter\n");
      return -1;
   }

   // Static vectors to zero
   Set_zero (state->frameEnergyHist, L_ENERGYHIST);

   // Initialize hangover handling
   state->bgHangover = 0;

   return 0;
}

------------------------------------------------------------------------------
 CAUTION [optional]
 [State any special notes, constraints or cautions for users of this function]

------------------------------------------------------------------------------
*/

Word16  Bgn_scd_reset(Bgn_scdState *state)
{
    if (state == (Bgn_scdState *) NULL)
    {
        /* fprintf(stderr, "Bgn_scd_reset: invalid parameter\n");  */
        return(-1);
    }

    /* Static vectors to zero */
    oscl_memset(state->frameEnergyHist, 0, L_ENERGYHIST*sizeof(Word16));

    /* Initialize hangover handling */
    state->bgHangover = 0;

    return(0);
}

/****************************************************************************/

/*
------------------------------------------------------------------------------
 FUNCTION NAME: Bgn_scd
------------------------------------------------------------------------------
 INPUT AND OUTPUT DEFINITIONS

 Inputs:
    st = pointer to state variables of type Bgn_scdState
    ltpGainHist[] = LTP gain history (Word16)
    speech[] = synthesis speech frame (Word16)
    voicedHangover = pointer to # of frames after last voiced frame (Word16)
    pOverflow      = pointer to overflow indicator (Flag)

 Outputs:
    st = function updates the state variables of type Bgn_scdState
        pointed to by st.
    voicedHangover = function updates the # of frames after last voiced
        frame pointed to by voicedHangover.
    pOverflow = 1 if the basic math function L_add() results in saturation.
                  else pOverflow is zero.

 Returns:
    inbgNoise = flag if background noise is present (Word16)

 Global Variables Used:
    None.

 Local Variables Needed:
    None.

------------------------------------------------------------------------------
 FUNCTION DESCRIPTION

 Characterize synthesis speech and detect background noise.

------------------------------------------------------------------------------
 REQUIREMENTS

 None

------------------------------------------------------------------------------
 REFERENCES

 bgnscd.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001

------------------------------------------------------------------------------
 PSEUDO-CODE

Word16 Bgn_scd (Bgn_scdState *st,      // i : State variables for bgn SCD
                Word16 ltpGainHist[],  // i : LTP gain history
                Word16 speech[],       // o : synthesis speech frame
                Word16 *voicedHangover // o : # of frames after last
                                              voiced frame
                )
{
   Word16 i;
   Word16 prevVoiced, inbgNoise;
   Word16 temp;
   Word16 ltpLimit, frameEnergyMin;
   Word16 currEnergy, noiseFloor, maxEnergy, maxEnergyLastPart;
   Word32 s;

   // Update the inBackgroundNoise flag (valid for use in next frame if BFI)
   // it now works as a energy detector floating on top
   // not as good as a VAD.

   currEnergy = 0;
   s = (Word32) 0;

   for (i = 0; i < L_FRAME; i++)
   {
       s = L_mac (s, speech[i], speech[i]);
   }

   s = L_shl(s, 2);

   currEnergy = extract_h (s);

   frameEnergyMin = 32767;

   for (i = 0; i < L_ENERGYHIST; i++)
   {
      if (sub(st->frameEnergyHist[i], frameEnergyMin) < 0)
         frameEnergyMin = st->frameEnergyHist[i];
   }

   noiseFloor = shl (frameEnergyMin, 4); // Frame Energy Margin of 16

   maxEnergy = st->frameEnergyHist[0];
   for (i = 1; i < L_ENERGYHIST-4; i++)
   {
      if ( sub (maxEnergy, st->frameEnergyHist[i]) < 0)
      {
         maxEnergy = st->frameEnergyHist[i];
      }
   }

   maxEnergyLastPart = st->frameEnergyHist[2*L_ENERGYHIST/3];
   for (i = 2*L_ENERGYHIST/3+1; i < L_ENERGYHIST; i++)
   {
      if ( sub (maxEnergyLastPart, st->frameEnergyHist[i] ) < 0)
      {
         maxEnergyLastPart = st->frameEnergyHist[i];
      }
   }

   inbgNoise = 0;        // false

   // Do not consider silence as noise
   // Do not consider continuous high volume as noise
   // Or if the current noise level is very low
   // Mark as noise if under current noise limit
   // OR if the maximum energy is below the upper limit

   if ( (sub(maxEnergy, LOWERNOISELIMIT) > 0) &&
        (sub(currEnergy, FRAMEENERGYLIMIT) < 0) &&
        (sub(currEnergy, LOWERNOISELIMIT) > 0) &&
        ( (sub(currEnergy, noiseFloor) < 0) ||
          (sub(maxEnergyLastPart, UPPERNOISELIMIT) < 0)))
   {
      if (sub(add(st->bgHangover, 1), 30) > 0)
      {
         st->bgHangover = 30;
      } else
      {
         st->bgHangover = add(st->bgHangover, 1);
      }
   }
   else
   {
      st->bgHangover = 0;
   }

   // make final decision about frame state , act somewhat cautiosly
   if (sub(st->bgHangover,1) > 0)
      inbgNoise = 1;       // true

   for (i = 0; i < L_ENERGYHIST-1; i++)
   {
      st->frameEnergyHist[i] = st->frameEnergyHist[i+1];
   }
   st->frameEnergyHist[L_ENERGYHIST-1] = currEnergy;

   // prepare for voicing decision; tighten the threshold after some
      time in noise
   ltpLimit = 13926;             // 0.85  Q14
   if (sub(st->bgHangover, 8) > 0)
   {
      ltpLimit = 15565;          // 0.95  Q14
   }
   if (sub(st->bgHangover, 15) > 0)
   {
      ltpLimit = 16383;          // 1.00  Q14
   }

   // weak sort of voicing indication.
   prevVoiced = 0;        // false

   if (sub(gmed_n(&ltpGainHist[4], 5), ltpLimit) > 0)
   {
      prevVoiced = 1;     // true
   }
   if (sub(st->bgHangover, 20) > 0) {
      if (sub(gmed_n(ltpGainHist, 9), ltpLimit) > 0)
      {
         prevVoiced = 1;  // true
      }
      else
      {
         prevVoiced = 0;  // false
      }
   }

   if (prevVoiced)
   {
      *voicedHangover = 0;
   }
   else
   {
      temp = add(*voicedHangover, 1);
      if (sub(temp, 10) > 0)
      {
         *voicedHangover = 10;
      }
      else
      {
         *voicedHangover = temp;
      }
   }

   return inbgNoise;
}

------------------------------------------------------------------------------
 CAUTION [optional]
 [State any special notes, constraints or cautions for users of this function]

------------------------------------------------------------------------------
*/

Word16  Bgn_scd(Bgn_scdState *st,       /* i : State variables for bgn SCD  */
                Word16 ltpGainHist[],  /* i : LTP gain history             */
                Word16 speech[],       /* o : synthesis speech frame       */
                Word16 *voicedHangover,/* o : # of frames after last
                                               voiced frame                 */
                Flag   *pOverflow
               )
{
    Word16  i;
    Word16  prevVoiced, inbgNoise;
    Word16  temp;
    Word16  ltpLimit, frameEnergyMin;
    Word16  currEnergy, noiseFloor, maxEnergy, maxEnergyLastPart;
    Word32  s, L_temp;

    /* Update the inBackgroundNoise flag (valid for use in next frame if BFI)   */
    /* it now works as a energy detector floating on top                        */
    /* not as good as a VAD.                                                    */

    s = (Word32) 0;

    for (i = L_FRAME - 1; i >= 0; i--)
    {
        L_temp = ((Word32) speech[i]) * speech[i];
        if (L_temp != (Word32) 0x40000000L)
        {
            L_temp = L_temp << 1;
        }
        else
        {
            L_temp = MAX_32;
        }
        s = L_add(s, L_temp, pOverflow);
    }

    /* s is a sum of squares, so don't need to check for neg overflow */
    if (s > (Word32)0x1fffffffL)
    {
        currEnergy = MAX_16;
    }
    else
    {
        currEnergy = (Word16)(s >> 14);
    }

    frameEnergyMin = 32767;
    for (i = L_ENERGYHIST - 1; i >= 0; i--)
    {
        if (st->frameEnergyHist[i] < frameEnergyMin)
        {
            frameEnergyMin = st->frameEnergyHist[i];
        }
    }

    /* Frame Energy Margin of 16 */
    L_temp = (Word32)frameEnergyMin << 4;
    if (L_temp != (Word32)((Word16) L_temp))
    {
        if (L_temp > 0)
        {
            noiseFloor = MAX_16;
        }
        else
        {
            noiseFloor = MIN_16;
        }
    }
    else
    {
        noiseFloor = (Word16)(L_temp);
    }

    maxEnergy = st->frameEnergyHist[0];
    for (i = L_ENERGYHIST - 5; i >= 1; i--)
    {
        if (maxEnergy < st->frameEnergyHist[i])
        {
            maxEnergy = st->frameEnergyHist[i];
        }
    }

    maxEnergyLastPart = st->frameEnergyHist[2*L_ENERGYHIST/3];
    for (i = 2 * L_ENERGYHIST / 3 + 1; i < L_ENERGYHIST; i++)
    {
        if (maxEnergyLastPart < st->frameEnergyHist[i])
        {
            maxEnergyLastPart = st->frameEnergyHist[i];
        }
    }

    /* Do not consider silence as noise */
    /* Do not consider continuous high volume as noise */
    /* Or if the current noise level is very low */
    /* Mark as noise if under current noise limit */
    /* OR if the maximum energy is below the upper limit */

    if ((maxEnergy > LOWERNOISELIMIT) &&
            (currEnergy < FRAMEENERGYLIMIT) &&
            (currEnergy > LOWERNOISELIMIT) &&
            ((currEnergy < noiseFloor) ||
             (maxEnergyLastPart < UPPERNOISELIMIT)))
    {
        if ((st->bgHangover + 1) > 30)
        {
            st->bgHangover = 30;
        }
        else
        {
            st->bgHangover += 1;
        }
    }
    else
    {
        st->bgHangover = 0;
    }

    /* make final decision about frame state , act somewhat cautiosly */

    if (st->bgHangover > 1)
    {
        inbgNoise = TRUE;
    }
    else
    {
        inbgNoise = FALSE;
    }

    for (i = 0; i < L_ENERGYHIST - 1; i++)
    {
        st->frameEnergyHist[i] = st->frameEnergyHist[i+1];
    }
    st->frameEnergyHist[L_ENERGYHIST-1] = currEnergy;

    /* prepare for voicing decision; tighten the threshold after some
       time in noise */

    if (st->bgHangover > 15)
    {
        ltpLimit = 16383;       /* 1.00  Q14 */
    }
    else if (st->bgHangover > 8)
    {
        ltpLimit = 15565;       /* 0.95  Q14 */
    }
    else
    {
        ltpLimit = 13926;       /* 0.85  Q14 */
    }

    /* weak sort of voicing indication. */
    prevVoiced = FALSE;

    if (gmed_n(&ltpGainHist[4], 5) > ltpLimit)
    {
        prevVoiced = TRUE;
    }

    if (st->bgHangover > 20)
    {
        if (gmed_n(ltpGainHist, 9) > ltpLimit)
        {
            prevVoiced = TRUE;
        }
        else
        {
            prevVoiced = FALSE;
        }
    }

    if (prevVoiced)
    {
        *voicedHangover = 0;
    }
    else
    {
        temp = *voicedHangover + 1;

        if (temp > 10)
        {
            *voicedHangover = 10;
        }
        else
        {
            *voicedHangover = temp;
        }
    }

    return(inbgNoise);
}


text:
package org.estatio.module.turnoveraggregate.dom;

import org.joda.time.LocalDate;

public enum AggregationPeriod {

    P_1M("1M", 1){
        @Override public LocalDate periodStartDateFor(final LocalDate periodEndDate) {
            return firstDayOfMonthFor(periodEndDate);
        }
    },
    P_2M("2M", 2) {
        @Override public LocalDate periodStartDateFor(final LocalDate periodEndDate) {
            final LocalDate dateMinus1Month = periodEndDate.minusMonths(1);
            return firstDayOfMonthFor(dateMinus1Month);
        }
    },
    P_3M("3M", 3) {
        @Override public LocalDate periodStartDateFor(final LocalDate periodEndDate) {
            final LocalDate dateMinus2Months = periodEndDate.minusMonths(2);
            return firstDayOfMonthFor(dateMinus2Months);
        }
    },
    P_6M("6M", 6) {
        @Override public LocalDate periodStartDateFor(final LocalDate periodEndDate) {
            final LocalDate dateMinus5Months = periodEndDate.minusMonths(5);
            return firstDayOfMonthFor(dateMinus5Months);
        }
    },
    P_9M("9M", 9) {
        @Override public LocalDate periodStartDateFor(final LocalDate periodEndDate) {
            final LocalDate dateMinus8Months = periodEndDate.minusMonths(8);
            return firstDayOfMonthFor(dateMinus8Months);
        }
    },
    P_12M("12M", 12) {
        @Override public LocalDate periodStartDateFor(final LocalDate periodEndDate) {
            final LocalDate dateMinus11Months = periodEndDate.minusMonths(11);
            return firstDayOfMonthFor(dateMinus11Months);
        }
    },
    P_12M_COVID("12M_COVID", 9) {
        @Override public LocalDate periodStartDateFor(final LocalDate periodEndDate) {
            final LocalDate dateMinus11Months = periodEndDate.minusMonths(11);
            return firstDayOfMonthFor(dateMinus11Months);
        }
    };

    private static LocalDate firstDayOfMonthFor(final LocalDate date) {
        return new LocalDate(date.getYear(), date.getMonthOfYear(), 1);
    }

    private final String name;
    private final int minNumberOfTurnovers;

    AggregationPeriod(final String name, final int minNumberOfTurnovers) {
        this.name = name;
        this.minNumberOfTurnovers = minNumberOfTurnovers;
    }

    public String getName(){
        return name;
    };

    public int getMinNumberOfTurnovers(){
        return minNumberOfTurnovers;
    }

    public abstract LocalDate periodStartDateFor(final LocalDate periodEndDate);

}


text:
Aplicación base con backbone y marionette

## Instalacción
### Dependencias
Para poder ejecutar esta aplicación en un entorno local debes tener instalado `node.js`. Si no lo tienes instalado, sigue las instrucciones [para instalar node.js](http://nodejs.org/).
### NPM
Una vez que hayas instalado node, puedes descargar el código de este repositorio.
Cuando lo hayas hecho, abre un terminal y dirigete hasta esa carpeta. Una vez allí, ejecuta:
```
npm install
```
Esto descargará e instalará todas las dependencias de npm para ejecutar el proyecto.
### Bower
Ahora necesitamos las librerias javascript que usa el proyecto. Para descargarlas lo haremos usando [bower](http://bower.io/) (previamente instalado con npm).
En la consola, ejecuta el siguiente comando para descargar las librerias javascript necesarias:
```
bower install
```
### Grunt
Si todo ha ido bien, y no ha habido errores al descargar los paquetes, tenemos el proyecto listo. Ejecuta el siguiente comando:
```
grunt serve
```
Esto ejecutará el gestor de tareas Grunt, ejecutando diferentes tareas: tests, compilacion de javascript, compilación de css... generando los archivos necesarios para una ejecutar el proyecto. Finalmente, creará una instancia de un servidor local y abrirá una página en el navegador con la página principal de la App.

# Código - Frameworks, Plugins, Librerias
En esta sección voy a explicar qué frameworks, librerias, plugins, etc.. he usado para el desarrollo y por qué.
### Yeoman
Para generar el código base de la aplicación he usado [Yeoman](https://github.com/yeoman/yo). Es muy util y rápido generarlo con un de los multiples generadores que vienen por defecto.
### Grunt
Yeoman configura por defecto Grunt como gestor de tareas. Muy util también para ejecutar cosas como la compilación de javascript o css desde la consola. Incluso viene con un comando para que esté "esperando" a cambios en diferentes archivos y ejecutar las tareas que sean necesarias.
### Backbone
Con yeoman he usado el generador de aplicación de Backbone. Para este proyecto he querido usar Backbone porque es un framework con el que ya tengo bastante experiencia y es muy flexible para poder modificar lo que quieras y hacer el framework a tu gusto. Además, está ya muy depurado y funciona muy bien y sin errores.
### Marionette
A pesar de que Backbone es un muy buen framework, tiene algunas carencias, como por ejemplo en la gestión de las vistas de tu aplicación. Por esto, he añadido [Marionette](http://marionettejs.com/) como complemento a Backbone, ya que mejora mucho la gestión de las vistas.
He de decir que no había usado Marionette antes, pero sabiendo como funciona Backbone no me ha sido muy complicado hacerme con ello.
### Hogan (plantillas)
Para el tema de plantillas también he querido aprender a usar algo nuevo, y en este caso he elegido [Hogan](http://twitter.github.io/hogan.js/). Realmente es muy sencillo de usar, se basa en [Mustache](http://mustache.github.io/), que ya había usado.
He querido meter las plantillas para evitar tener código HTML duplicado por todos lados y que el proyecto sea más flexible y extensible. Además, hogan me ha permitido compilar las plantillas en javascript para que estas estén disponibles en todos lados a un método de distancia. (compilación de plantillas gracias a Grunt :D)
### Sass
Para el CSS he usado [Sass](http://sass-lang.com/), pero con la sintaxys de scss. Al principio pensé en usar algun framework de css, como bootstrap o foundation, pero finalmente lo descarté ya que "sobraba" más código de que iba a usar realmente.
Si que he usado [Compass](http://compass-style.org/) y algunas de sus funciones para hacer que la web se vea bien en los diferentes navegadores.
### Iconos
Para el tema de iconos, FontAwesome, que es una fuente de iconos. Ya la había usado antes y me gusta el estilo de los iconos y cómo se usan.
### Jquery-Storage-API
Para el manejo de localstorage he usado este plugin de jquery, sencillo y funcional.

## APP Backend
El repositorio con el backend de la aplicación está disponible también en https://github.com/juan-cb/Delines-Backend
El backend proporciona una API para obtener y guardar los datos de posicionamiento obtenidos desde este cliente. Este backend se ha desarrollado usando Django (https://www.djangoproject.com/), Django REST Framework (http://www.django-rest-framework.org/) y MySQL (https://www.mysql.com/).


text:
from copy import deepcopy
from cms.extensions.toolbar import ExtensionToolbar
from cms.toolbar_pool import toolbar_pool
from cms.utils.urlutils import admin_reverse
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from django.contrib.sites.models import Site

from cms.api import create_page, create_title
from cms.constants import PUBLISHER_STATE_DIRTY
from cms.extensions import extension_pool
from cms.extensions import TitleExtension
from cms.extensions import PageExtension
from cms.models import Page
from cms.test_utils.project.extensionapp.models import MyPageExtension, MyTitleExtension
from cms.test_utils.testcases import CMSTestCase as TestCase, URL_CMS_PAGE_ADD
from cms.tests.test_admin import AdminTestsBase

class ExtensionsTestCase(TestCase):
    def test_register_extension(self):
        initial_extension_count = len(extension_pool.page_extensions)
        # --- None extension registering -----------------------------
        from cms.exceptions import SubClassNeededError
        none_extension = self.get_none_extension_class()
        self.assertRaises(SubClassNeededError, extension_pool.register, none_extension)
        self.assertEqual(len(extension_pool.page_extensions), initial_extension_count)
        self.assertEqual(len(extension_pool.title_extensions), initial_extension_count)

        # --- Page registering ---------------------------------------
        page_extension = self.get_page_extension_class()

        # register first time
        extension_pool.register(page_extension)
        self.assertEqual(len(extension_pool.page_extensions), initial_extension_count+1)

        # register second time
        extension_pool.register(page_extension)
        self.assertEqual(len(extension_pool.page_extensions), initial_extension_count+1)

        self.assertIs(extension_pool.signaling_activated, True)

        # --- Title registering --------------------------------------
        title_extension = self.get_title_extension_class()

        # register first time
        extension_pool.register(title_extension)
        self.assertEqual(len(extension_pool.title_extensions), initial_extension_count+1)

        # register second time
        extension_pool.register(title_extension)
        self.assertEqual(len(extension_pool.title_extensions), initial_extension_count+1)

        self.assertIs(extension_pool.signaling_activated, True)

        # --- Unregister ---------------------------------------------
        extension_pool.unregister(page_extension)
        self.assertEqual(len(extension_pool.page_extensions), initial_extension_count)

        extension_pool.unregister(title_extension)
        self.assertEqual(len(extension_pool.title_extensions), initial_extension_count)

        # Unregister an object that is not registered yet
        extension_pool.unregister(page_extension)
        extension_pool.unregister(title_extension)

    def get_page_extension_class(self):
        from django.db import models

        class TestPageExtension(PageExtension):
            content = models.CharField('Content', max_length=50)

            class Meta:
                abstract = True

        return TestPageExtension

    def get_title_extension_class(self):
        from django.db import models

        class TestTitleExtension(TitleExtension):
            content = models.CharField('Content', max_length=50)

            class Meta:
                abstract = True

        return TestTitleExtension

    def get_none_extension_class(self):
        class TestNoneExtension(object):
            pass

        return TestNoneExtension

    def test_copy_extensions(self):
        root = create_page('Root', "nav_playground.html", "en", published=True)
        page = create_page('Test Page Extension', "nav_playground.html", "en",
                           parent=root.get_draft_object())
        subpage = create_page('Test subpage Extension', "nav_playground.html", "en",
                              parent=page)
        page = Page.objects.get(pk=page.pk)
        page_extension = MyPageExtension(extended_object=page, extra='page extension 1')
        page_extension.save()
        page.mypageextension = page_extension
        title = page.get_title_obj()
        title_extension = MyTitleExtension(extended_object=title, extra_title='title extension 1')
        title_extension.save()
        page.mytitleextension = title_extension

        subpage_extension = MyPageExtension(extended_object=subpage, extra='page extension 2')
        subpage_extension.save()
        subpage.mypageextension = subpage_extension
        subtitle = subpage.get_title_obj()
        subtitle_extension = MyTitleExtension(extended_object=subtitle, extra_title='title extension 2')
        subtitle_extension.save()
        subpage.mytitleextension = subtitle_extension

        # asserting original extensions
        self.assertEqual(len(extension_pool.get_page_extensions()), 2)
        self.assertEqual(len(extension_pool.get_title_extensions()), 2)

        copied_page = page.copy_page(None, page.site, position='last-child')

        # asserting original + copied extensions
        self.assertEqual(len(extension_pool.get_page_extensions()), 4)
        self.assertEqual(len(extension_pool.get_title_extensions()), 4)

        # testing extension content
        old_page_extensions = [page_extension, subpage_extension]
        old_title_extension = [title_extension, subtitle_extension]
        for index, new_page in enumerate([copied_page] + list(copied_page.get_descendants())):
            self.assertEqual(extension_pool.get_page_extensions(new_page)[0].extra,
                             old_page_extensions[index].extra)
            self.assertEqual(extension_pool.get_title_extensions(new_page.title_set.get(language='en'))[0].extra_title,
                             old_title_extension[index].extra_title)
            # check that objects are actually different
            self.assertNotEqual(extension_pool.get_page_extensions(new_page)[0].pk,
                                old_page_extensions[index].pk)
            self.assertNotEqual(extension_pool.get_title_extensions(new_page.title_set.get(language='en'))[0].pk,
                                old_title_extension[index].pk)

        # Test deleting original page for #3987
        page.delete()
        # asserting original extensions are gone, but copied ones should still exist
        self.assertEqual(len(extension_pool.get_page_extensions()), 2)
        self.assertEqual(len(extension_pool.get_title_extensions()), 2)

    def test_publish_page_extension(self):
        page = create_page('Test Page Extension', "nav_playground.html", "en")
        page_extension = MyPageExtension(extended_object=page, extra='page extension 1')
        page_extension.save()
        page.mypageextension = page_extension

        # publish first time
        page.publish('en')
        self.assertEqual(page_extension.extra, page.publisher_public.mypageextension.extra)
        self.assertEqual(page.get_publisher_state('en'), 0)
        # change and publish again
        page = Page.objects.get(pk=page.pk)
        page_extension = page.mypageextension
        page_extension.extra = 'page extension 1 - changed'
        page_extension.save()
        self.assertEqual(page.get_publisher_state('en', True), PUBLISHER_STATE_DIRTY)
        page.publish('en')
        self.assertEqual(page.get_publisher_state('en', True), 0)
        # delete
        page_extension.delete()
        self.assertFalse(MyPageExtension.objects.filter(pk=page_extension.pk).exists())
        self.assertEqual(page.get_publisher_state('en', True), PUBLISHER_STATE_DIRTY)

    def test_publish_title_extension(self):
        page = create_page('Test Title Extension', "nav_playground.html", "en")
        title = page.get_title_obj()
        title_extension = MyTitleExtension(extended_object=title, extra_title='title extension 1')
        title_extension.save()
        page.mytitleextension = title_extension

        # publish first time
        page.publish('en')
        # import ipdb; ipdb.set_trace()
        self.assertEqual(page.get_publisher_state('en'), 0)
        self.assertEqual(title_extension.extra_title, page.publisher_public.get_title_obj().mytitleextension.extra_title)

        # change and publish again
        page = Page.objects.get(pk=page.pk)
        title = page.get_title_obj()
        title_extension = title.mytitleextension
        title_extension.extra_title = 'title extension 1 - changed'
        title_extension.save()
        self.assertEqual(page.get_publisher_state('en', True), PUBLISHER_STATE_DIRTY)
        page.publish('en')
        self.assertEqual(page.get_publisher_state('en', True), 0)

        # delete
        title_extension.delete()
        self.assertFalse(MyTitleExtension.objects.filter(pk=title_extension.pk).exists())

class ExtensionAdminTestCase(AdminTestsBase):
    def setUp(self):
        User = get_user_model()

        self.admin, self.normal_guy = self._get_guys()

        if get_user_model().USERNAME_FIELD == 'email':
            self.no_page_permission_user = User.objects.create_user('no_page_permission', 'test2@test.com', 'test2@test.com')
        else:
            self.no_page_permission_user = User.objects.create_user('no_page_permission', 'test2@test.com', 'no_page_permission')

        self.no_page_permission_user.is_staff = True
        self.no_page_permission_user.is_active = True
        self.no_page_permission_user.save()
        [self.no_page_permission_user.user_permissions.add(p) for p in Permission.objects.filter(
            codename__in=[
                'change_mypageextension', 'change_mytitleextension',
                'add_mypageextension', 'add_mytitleextension',
                'delete_mypageextension', 'delete_mytitleextension',
            ]
        )]
        self.site = Site.objects.get(pk=1)
        self.page = create_page(
            'My Extension Page', 'nav_playground.html', 'en',
            site=self.site, created_by=self.admin)
        self.page_title = self.page.get_title_obj('en')
        create_title('de', 'de title', self.page)
        self.page_extension = MyPageExtension.objects.create(
            extended_object=self.page,
            extra="page extension text")
        self.title_extension = MyTitleExtension.objects.create(
            extended_object=self.page.get_title_obj(),
            extra_title="title extension text")

        self.page_without_extension = create_page(
            'A Page', 'nav_playground.html', 'en',
            site=self.site, created_by=self.admin)
        self.page_title_without_extension = self.page_without_extension.get_title_obj()

    def test_duplicate_extensions(self):
        with self.login_user_context(self.admin):
            # create page copy
            page_data = {
                'title': 'type1', 'slug': 'type1', '_save': 1, 'template': 'nav_playground.html',
                'site': 1, 'language': 'en'
            }
            self.assertEqual(Page.objects.all().count(), 2)
            self.assertEqual(MyPageExtension.objects.all().count(), 1)
            self.assertEqual(MyTitleExtension.objects.all().count(), 1)
            self.client.post(
                "%s?position=first-child&copy_target=%s&language=en" % (
                    URL_CMS_PAGE_ADD, self.page.pk
                ),
                data=page_data)
            # Check that page and its extensions have been copied
            self.assertEqual(Page.objects.all().count(), 3)
            self.assertEqual(MyPageExtension.objects.all().count(), 2)
            self.assertEqual(MyTitleExtension.objects.all().count(), 2)

    def test_page_type_extensions(self):
        with self.login_user_context(self.admin):
            self.client.get(
                "%s?copy_target=%s&language=%s" % (
                    admin_reverse("cms_page_add_page_type"), self.page.pk, 'en'
                )
            )
            page_types = Page.objects.get(reverse_id='page_types')

            # create page copy
            page_data = {
                'title': 'type1', 'slug': 'type1', '_save': 1, 'template': 'nav_playground.html',
                'site': 1, 'language': 'en'
            }
            self.assertEqual(Page.objects.all().count(), 3)
            self.assertEqual(MyPageExtension.objects.all().count(), 1)
            self.assertEqual(MyTitleExtension.objects.all().count(), 1)
            self.client.post(
                "%s?target=%s&position=first-child&add_page_type=1"
                "&copy_target=%s&language=en" % (
                    URL_CMS_PAGE_ADD, page_types.pk, self.page.pk
                ),
                data=page_data)
            # Check that new page type has extensions from source page
            self.assertEqual(Page.objects.all().count(), 4)
            self.assertEqual(MyPageExtension.objects.all().count(), 2)
            self.assertEqual(MyTitleExtension.objects.all().count(), 2)

    def test_admin_page_extension(self):
        with self.login_user_context(self.admin):
            # add a new extension
            response = self.client.get(
                admin_reverse('extensionapp_mypageextension_add') + '?extended_object=%s' % self.page_without_extension.pk
            )
            self.assertEqual(response.status_code, 200)
            # make sure there is no extension yet
            self.assertFalse(MyPageExtension.objects.filter(extended_object=self.page_without_extension).exists())
            post_data = {
                'extra': 'my extra'
            }
            response = self.client.post(
                admin_reverse('extensionapp_mypageextension_add') + '?extended_object=%s' % self.page_without_extension.pk,
                post_data, follow=True
            )
            created_page_extension = MyPageExtension.objects.get(extended_object=self.page_without_extension)

            # can delete extension
            response = self.client.post(
                admin_reverse('extensionapp_mypageextension_delete', args=(created_page_extension.pk,)),
                {'post': 'yes'}, follow=True
            )
            self.assertFalse(MyPageExtension.objects.filter(extended_object=self.page_without_extension).exists())

            # accessing the add view on a page that already has an extension should redirect
            response = self.client.get(
                admin_reverse('extensionapp_mypageextension_add') + '?extended_object=%s' % self.page.pk
            )
            self.assertRedirects(response, admin_reverse('extensionapp_mypageextension_change', args=(self.page_extension.pk,)))

            # saving an extension should work without the GET parameter
            post_data = {
                'extra': 'my extra text'
            }
            self.client.post(
                admin_reverse('extensionapp_mypageextension_change', args=(self.page_extension.pk,)),
                post_data, follow=True
            )
            self.assertTrue(MyPageExtension.objects.filter(extra='my extra text', pk=self.page_extension.pk).exists())

        with self.login_user_context(self.no_page_permission_user):
            # can't save if user does not have permissions to change the page
            post_data = {
                'extra': 'try to change extra text'
            }
            response = self.client.post(
                admin_reverse('extensionapp_mypageextension_change', args=(self.page_extension.pk,)),
                post_data, follow=True
            )
            self.assertEqual(response.status_code, 403)

            # can't delete without page permission
            response = self.client.post(
                admin_reverse('extensionapp_mypageextension_delete', args=(self.page_extension.pk,)),
                {'post': 'yes'}, follow=True
            )
            self.assertEqual(response.status_code, 403)
            self.assertTrue(MyPageExtension.objects.filter(extended_object=self.page).exists())

    def test_toolbar_page_extension(self):
        old_toolbars = deepcopy(toolbar_pool.toolbars)
        class SampleExtension(ExtensionToolbar):
            model = MyPageExtension  # The PageExtension / TitleExtension you are working with

            def populate(self):
                current_page_menu = self._setup_extension_toolbar()
                if current_page_menu:
                    position = 0
                    page_extension, url = self.get_page_extension_admin()
                    if url:
                        current_page_menu.add_modal_item('TestItem', url=url,
                                                         disabled=not self.toolbar.edit_mode,
                                                         position=position)
        toolbar_pool.register(SampleExtension)
        with self.login_user_context(self.admin):
            response = self.client.get('/en/?edit')
            self.assertIn("TestItem", response.rendered_content)
        toolbar_pool.toolbars = old_toolbars

    def test_toolbar_title_extension(self):
        old_toolbars = deepcopy(toolbar_pool.toolbars)

        class SampleExtension(ExtensionToolbar):
            model = MyTitleExtension

            def populate(self):
                current_page_menu = self._setup_extension_toolbar()
                if current_page_menu:
                    position = 0
                    urls = self.get_title_extension_admin()
                    for title_extension, url in urls:
                        current_page_menu.add_modal_item('TestItem', url=url,
                                                         disabled=not self.toolbar.edit_mode,
                                                         position=position)
        toolbar_pool.register(SampleExtension)
        with self.login_user_context(self.admin):
            response = self.client.get('/en/?edit')
            self.assertIn("TestItem", response.rendered_content)
        toolbar_pool.toolbars = old_toolbars

    def test_admin_title_extension(self):
        with self.login_user_context(self.admin):
            # add a new extension
            response = self.client.get(
                admin_reverse('extensionapp_mytitleextension_add') + '?extended_object=%s' % self.page_title_without_extension.pk
            )
            self.assertEqual(response.status_code, 200)
            # make sure there is no extension yet
            self.assertFalse(MyTitleExtension.objects.filter(extended_object=self.page_title_without_extension).exists())
            post_data = {
                'extra_title': 'my extra title'
            }
            self.client.post(
                admin_reverse('extensionapp_mytitleextension_add') + '?extended_object=%s' % self.page_title_without_extension.pk,
                post_data, follow=True
            )
            created_title_extension = MyTitleExtension.objects.get(extended_object=self.page_title_without_extension)

            # can delete extension
            self.client.post(
                admin_reverse('extensionapp_mytitleextension_delete', args=(created_title_extension.pk,)),
                {'post': 'yes'}, follow=True
            )
            self.assertFalse(MyTitleExtension.objects.filter(extended_object=self.page_title_without_extension).exists())

            # accessing the add view on a page that already has an extension should redirect
            response = self.client.get(
                admin_reverse('extensionapp_mytitleextension_add') + '?extended_object=%s' % self.page_title.pk
            )
            self.assertRedirects(response, admin_reverse('extensionapp_mytitleextension_change', args=(self.title_extension.pk,)))

            # saving an extension should work without the GET parameter
            post_data = {
                'extra_title': 'my extra text'
            }
            self.client.post(
                admin_reverse('extensionapp_mytitleextension_change', args=(self.title_extension.pk,)),
                post_data, follow=True
            )
            self.assertTrue(MyTitleExtension.objects.filter(extra_title='my extra text', pk=self.title_extension.pk).exists())

        with self.login_user_context(self.no_page_permission_user):
            # can't save if user does not have permissions to change the page
            post_data = {
                'extra_title': 'try to change extra text'
            }
            response = self.client.post(
                admin_reverse('extensionapp_mytitleextension_change', args=(self.title_extension.pk,)),
                post_data, follow=True
            )
            self.assertEqual(response.status_code, 403)

            # can't delete without page permission
            response = self.client.post(
                admin_reverse('extensionapp_mytitleextension_delete', args=(self.title_extension.pk,)),
                {'post': 'yes'}, follow=True
            )
            self.assertEqual(response.status_code, 403)
            self.assertTrue(MyTitleExtension.objects.filter(extended_object=self.page_title).exists())


text:
describe('layouts.onRemoved ', () => {

    const defaultLayout = {
        name: "default",
        type: "Workspace",
        metadata: {},
        components: [
            {
                type: "Workspace",
                state: {
                    children: [
                        {
                            type: "column",
                            children: [
                                {
                                    type: "row",
                                    children: [
                                        {
                                            type: "group",
                                            children: [
                                                {
                                                    type: "window",
                                                    config: {
                                                        appName: "dummyApp"
                                                    }
                                                }
                                            ],
                                            config: {}
                                        }
                                    ],
                                    config: {}
                                }
                            ],
                            config: {}
                        }
                    ],
                    config: {
                        name: "default",
                        title: "Untitled 1"
                    },
                    context: {}
                }
            }
        ]
    };

    let processedLayout;

    const secondLayout = {
        name: "second",
        type: "Workspace",
        metadata: {},
        components: [
            {
                type: "Workspace",
                state: {
                    children: [
                        {
                            type: "column",
                            children: [
                                {
                                    type: "row",
                                    children: [
                                        {
                                            type: "group",
                                            children: [
                                                {
                                                    type: "window",
                                                    config: {
                                                        appName: "dummyApp"
                                                    }
                                                }
                                            ],
                                            config: {}
                                        }
                                    ],
                                    config: {}
                                }
                            ],
                            config: {}
                        }
                    ],
                    config: {
                        name: "second",
                        title: "Untitled 1"
                    },
                    context: {}
                }
            }
        ]
    };

    const testLayoutsNames = [defaultLayout.name, secondLayout.name];

    let unSubFuncs = [];
    let timeout;

    before(() => coreReady);

    beforeEach(async () => {
        await glue.workspaces.layouts.import([defaultLayout]);
        processedLayout = (await glue.workspaces.layouts.export()).find((layout) => layout.name === defaultLayout.name);
    });

    afterEach(async () => {
        if (timeout) {
            clearTimeout(timeout);
            timeout = null;
        }

        unSubFuncs.forEach((unSub) => {
            if (typeof unSub === "function") {
                unSub();
            }
        });
        unSubFuncs = [];

        await Promise.all(testLayoutsNames.map((name) => glue.workspaces.layouts.delete(name)));
    });

    it('should return a promise, which resolves with a function', async () => {
        const layoutRemovedPromise = glue.workspaces.layouts.onRemoved(() => { });

        expect(layoutRemovedPromise.then).to.be.a("function");
        expect(layoutRemovedPromise.catch).to.be.a("function");

        const layoutRemovedResult = await layoutRemovedPromise;

        expect(layoutRemovedResult).to.be.a("function");

        unSubFuncs.push(layoutRemovedResult);
    });

    it('should notify when a layout is removed', (done) => {
        const ready = gtf.waitFor(2, done);

        glue.workspaces.layouts.onRemoved(ready)
            .then((unSub) => {
                unSubFuncs.push(unSub);
                return glue.workspaces.layouts.delete(defaultLayout.name);
            })
            .then(ready)
            .catch(done);
    });

    it('should not notify when trying to remove an non-existing layout', (done) => {
        const ready = gtf.waitFor(2, done);
        timeout = setTimeout(ready, 3000);

        glue.workspaces.layouts.onRemoved(() => done("Should not have been invoked, because the layout does not exist"))
            .then((unSub) => {
                unSubFuncs.push(unSub);
                return glue.workspaces.layouts.delete("non-existing");
            })
            .then(ready)
            .catch(done);
    });

    it('the provided object should be a complete layout', (done) => {
        const ready = gtf.waitFor(2, done);

        glue.workspaces.layouts.onRemoved((layout) => {
            try {
                expect(layout).to.eql(processedLayout);
                ready()
            } catch (error) {
                done(error);
            }
        })
            .then((unSub) => {
                unSubFuncs.push(unSub);
                return glue.workspaces.layouts.delete(defaultLayout.name);
            })
            .then(ready)
            .catch(done);
    });

    it('should notify exactly once when a layout is removed', (done) => {
        const ready = gtf.waitFor(3, done);
        timeout = setTimeout(ready, 3000);
        let called = false;

        glue.workspaces.layouts.onRemoved(() => {
            if (called) {
                done("Should not have been called, because this layout was already announced");
                return;
            }
            called = true;
            ready();
        })
            .then((unSub) => {
                unSubFuncs.push(unSub);
                return glue.workspaces.layouts.delete(defaultLayout.name);
            })
            .then(ready)
            .catch(done);
    });

    it('should notify twice when two layouts are removed (sequentially)', (done) => {
        const ready = gtf.waitFor(3, done);

        glue.workspaces.layouts.import([secondLayout], "merge")
            .then(() => {
                return glue.workspaces.layouts.onRemoved(ready)
            })
            .then((unSub) => {
                unSubFuncs.push(unSub);
                return glue.workspaces.layouts.delete(defaultLayout.name);
            })
            .then(() => glue.workspaces.layouts.delete(secondLayout.name))
            .then(ready)
            .catch(done);
    });

    it('should notify twice when two layout are removed (parallel)', (done) => {
        const ready = gtf.waitFor(3, done);

        glue.workspaces.layouts.import([secondLayout], "merge")
            .then(() => {
                return glue.workspaces.layouts.onRemoved(ready)
            })
            .then((unSub) => {
                unSubFuncs.push(unSub);
                return Promise.all([
                    glue.workspaces.layouts.delete(defaultLayout.name),
                    glue.workspaces.layouts.delete(secondLayout.name)
                ]);
            })
            .then(ready)
            .catch(done);
    });

    it('should notify twice when two layout are removed (on notify)', (done) => {
        const ready = gtf.waitFor(3, done);
        let called = false;

        glue.workspaces.layouts.import([secondLayout], "merge")
            .then(() => {
                return glue.workspaces.layouts.onRemoved(() => {
                    if (!called) {
                        called = true;
                        glue.workspaces.layouts.delete(secondLayout.name).then(ready).catch(done);
                    }
                    ready();
                })
            })
            .then((unSub) => {
                unSubFuncs.push(unSub);
                return glue.workspaces.layouts.delete(defaultLayout.name);
            })
            .then(ready)
            .catch(done);
    });

    it('should not notify when immediately unsubscribed', (done) => {
        const ready = gtf.waitFor(2, done);

        timeout = setTimeout(ready, 3000);

        glue.workspaces.layouts.onRemoved(() => {
                done("Should not have been called.");
            })
            .then((unSub) => {
                unSub();
                return glue.workspaces.layouts.delete(defaultLayout.name);
            })
            .then(ready)
            .catch(done);
    });

    it('should not notify when unsubscribing after receiving notifications', (done) => {
        const ready = gtf.waitFor(4, done);
        let called = false;
        let unSub;
        timeout = setTimeout(ready, 3000);

        glue.workspaces.layouts.import([secondLayout], "merge")
            .then(() => {
                return glue.workspaces.layouts.onRemoved(() => {
                    if (!called) {
                        called = true;
                        unSub();
                        glue.workspaces.layouts.delete(secondLayout.name).then(ready).catch(done);
                        ready();
                        return;
                    }
                    done("Should not have been called, because unsub was invoked");
                })
            })
            .then((un) => {
                unSub = un;
                return glue.workspaces.layouts.delete(defaultLayout.name);
            })
            .then(ready)
            .catch(done);
    });

    [
        undefined,
        null,
        42,
        true,
        {},
        { test: () => { } },
        "function",
        [() => { }]
    ].forEach((input) => {
        it(`should reject if the provided parameter is not a function: ${JSON.stringify(input)}`, (done) => {
            glue.workspaces.layouts.onRemoved(input)
                .then((unSub) => {
                    unSubFuncs.push(unSub);
                    done(`Should have resolved, because the provided parameter is not valid: ${JSON.stringify(input)}`);
                })
                .catch(() => {
                    done();
                });
        });
    });

});


text:
// Code generated by lister-gen. DO NOT EDIT.

package v1alpha3

// DestinationRuleListerExpansion allows custom methods to be added to
// DestinationRuleLister.
type DestinationRuleListerExpansion interface{}

// DestinationRuleNamespaceListerExpansion allows custom methods to be added to
// DestinationRuleNamespaceLister.
type DestinationRuleNamespaceListerExpansion interface{}

// GatewayListerExpansion allows custom methods to be added to
// GatewayLister.
type GatewayListerExpansion interface{}

// GatewayNamespaceListerExpansion allows custom methods to be added to
// GatewayNamespaceLister.
type GatewayNamespaceListerExpansion interface{}

// VirtualServiceListerExpansion allows custom methods to be added to
// VirtualServiceLister.
type VirtualServiceListerExpansion interface{}

// VirtualServiceNamespaceListerExpansion allows custom methods to be added to
// VirtualServiceNamespaceLister.
type VirtualServiceNamespaceListerExpansion interface{}


text: ./insert_fwrules_real.sh fxp0 sudo


text:
module Chewy
  class Error < StandardError
  end

  class UndefinedIndex < Error
  end

  class UndefinedType < Error
  end

  class UnderivableType < Error
  end

  class UndefinedUpdateStrategy < Error
    def initialize type
      super <<-MESSAGE
Index update strategy is undefined in current context.
Please wrap your code with `Chewy.strategy(:strategy_name) block.`
      MESSAGE
    end
  end

  class DocumentNotFound < Error
  end

  class ImportFailed < Error
    def initialize type, errors
      message = "Import failed for `#{type}` with:\n"
      errors.each do |action, errors|
        message << "    #{action.to_s.humanize} errors:\n"
        errors.each do |error, documents|
          message << "      `#{error}`\n"
          message << "        on #{documents.count} documents: #{documents}\n"
        end
      end
      super message
    end
  end
end