text:
package io.reactivex.internal.operators.observable;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;

import java.util.*;
import java.util.concurrent.*;

import org.junit.*;
import org.mockito.Mockito;

import io.reactivex.*;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.exceptions.TestException;

public class ObservableToListTest {

    @Test
    public void testListObservable() {
        Observable<String> w = Observable.fromIterable(Arrays.asList("one", "two", "three"));
        Observable<List<String>> observable = w.toList().toObservable();

        Observer<List<String>> observer = TestHelper.mockObserver();
        observable.subscribe(observer);
        verify(observer, times(1)).onNext(Arrays.asList("one", "two", "three"));
        verify(observer, Mockito.never()).onError(any(Throwable.class));
        verify(observer, times(1)).onComplete();
    }

    @Test
    public void testListViaObservableObservable() {
        Observable<String> w = Observable.fromIterable(Arrays.asList("one", "two", "three"));
        Observable<List<String>> observable = w.toList().toObservable();

        Observer<List<String>> observer = TestHelper.mockObserver();
        observable.subscribe(observer);
        verify(observer, times(1)).onNext(Arrays.asList("one", "two", "three"));
        verify(observer, Mockito.never()).onError(any(Throwable.class));
        verify(observer, times(1)).onComplete();
    }

    @Test
    public void testListMultipleSubscribersObservable() {
        Observable<String> w = Observable.fromIterable(Arrays.asList("one", "two", "three"));
        Observable<List<String>> observable = w.toList().toObservable();

        Observer<List<String>> o1 = TestHelper.mockObserver();
        observable.subscribe(o1);

        Observer<List<String>> o2 = TestHelper.mockObserver();
        observable.subscribe(o2);

        List<String> expected = Arrays.asList("one", "two", "three");

        verify(o1, times(1)).onNext(expected);
        verify(o1, Mockito.never()).onError(any(Throwable.class));
        verify(o1, times(1)).onComplete();

        verify(o2, times(1)).onNext(expected);
        verify(o2, Mockito.never()).onError(any(Throwable.class));
        verify(o2, times(1)).onComplete();
    }

    @Test
    @Ignore("Null values are not allowed")
    public void testListWithNullValueObservable() {
        Observable<String> w = Observable.fromIterable(Arrays.asList("one", null, "three"));
        Observable<List<String>> observable = w.toList().toObservable();

        Observer<List<String>> observer = TestHelper.mockObserver();
        observable.subscribe(observer);
        verify(observer, times(1)).onNext(Arrays.asList("one", null, "three"));
        verify(observer, Mockito.never()).onError(any(Throwable.class));
        verify(observer, times(1)).onComplete();
    }

    @Test
    public void testListWithBlockingFirstObservable() {
        Observable<String> o = Observable.fromIterable(Arrays.asList("one", "two", "three"));
        List<String> actual = o.toList().toObservable().blockingFirst();
        Assert.assertEquals(Arrays.asList("one", "two", "three"), actual);
    }

    @SuppressWarnings("unchecked")
    @Test
    public void capacityHintObservable() {
        Observable.range(1, 10)
        .toList(4)
        .toObservable()
        .test()
        .assertResult(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
    }

    @Test
    public void testList() {
        Observable<String> w = Observable.fromIterable(Arrays.asList("one", "two", "three"));
        Single<List<String>> observable = w.toList();

        SingleObserver<List<String>> observer = TestHelper.mockSingleObserver();
        observable.subscribe(observer);
        verify(observer, times(1)).onSuccess(Arrays.asList("one", "two", "three"));
        verify(observer, Mockito.never()).onError(any(Throwable.class));
    }

    @Test
    public void testListViaObservable() {
        Observable<String> w = Observable.fromIterable(Arrays.asList("one", "two", "three"));
        Single<List<String>> observable = w.toList();

        SingleObserver<List<String>> observer = TestHelper.mockSingleObserver();
        observable.subscribe(observer);
        verify(observer, times(1)).onSuccess(Arrays.asList("one", "two", "three"));
        verify(observer, Mockito.never()).onError(any(Throwable.class));
    }

    @Test
    public void testListMultipleSubscribers() {
        Observable<String> w = Observable.fromIterable(Arrays.asList("one", "two", "three"));
        Single<List<String>> observable = w.toList();

        SingleObserver<List<String>> o1 = TestHelper.mockSingleObserver();
        observable.subscribe(o1);

        SingleObserver<List<String>> o2 = TestHelper.mockSingleObserver();
        observable.subscribe(o2);

        List<String> expected = Arrays.asList("one", "two", "three");

        verify(o1, times(1)).onSuccess(expected);
        verify(o1, Mockito.never()).onError(any(Throwable.class));

        verify(o2, times(1)).onSuccess(expected);
        verify(o2, Mockito.never()).onError(any(Throwable.class));
    }

    @Test
    @Ignore("Null values are not allowed")
    public void testListWithNullValue() {
        Observable<String> w = Observable.fromIterable(Arrays.asList("one", null, "three"));
        Single<List<String>> observable = w.toList();

        SingleObserver<List<String>> observer = TestHelper.mockSingleObserver();
        observable.subscribe(observer);
        verify(observer, times(1)).onSuccess(Arrays.asList("one", null, "three"));
        verify(observer, Mockito.never()).onError(any(Throwable.class));
    }

    @Test
    public void testListWithBlockingFirst() {
        Observable<String> o = Observable.fromIterable(Arrays.asList("one", "two", "three"));
        List<String> actual = o.toList().blockingGet();
        Assert.assertEquals(Arrays.asList("one", "two", "three"), actual);
    }

    static void await(CyclicBarrier cb) {
        try {
            cb.await();
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        } catch (BrokenBarrierException ex) {
            ex.printStackTrace();
        }
    }

    @SuppressWarnings("unchecked")
    @Test
    public void capacityHint() {
        Observable.range(1, 10)
        .toList(4)
        .test()
        .assertResult(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
    }

    @Test
    public void dispose() {
        TestHelper.checkDisposed(Observable.just(1).toList().toObservable());

        TestHelper.checkDisposed(Observable.just(1).toList());
    }

    @SuppressWarnings("unchecked")
    @Test
    public void error() {
        Observable.error(new TestException())
        .toList()
        .toObservable()
        .test()
        .assertFailure(TestException.class);
    }

    @SuppressWarnings("unchecked")
    @Test
    public void errorSingle() {
        Observable.error(new TestException())
        .toList()
        .test()
        .assertFailure(TestException.class);
    }

    @SuppressWarnings("unchecked")
    @Test
    public void collectionSupplierThrows() {
        Observable.just(1)
        .toList(new Callable<Collection<Integer>>() {
            @Override
            public Collection<Integer> call() throws Exception {
                throw new TestException();
            }
        })
        .toObservable()
        .test()
        .assertFailure(TestException.class);
    }

    @SuppressWarnings("unchecked")
    @Test
    public void collectionSupplierReturnsNull() {
        Observable.just(1)
        .toList(new Callable<Collection<Integer>>() {
            @Override
            public Collection<Integer> call() throws Exception {
                return null;
            }
        })
        .toObservable()
        .test()
        .assertFailure(NullPointerException.class)
        .assertErrorMessage("The collectionSupplier returned a null collection. Null values are generally not allowed in 2.x operators and sources.");
    }

    @SuppressWarnings("unchecked")
    @Test
    public void singleCollectionSupplierThrows() {
        Observable.just(1)
        .toList(new Callable<Collection<Integer>>() {
            @Override
            public Collection<Integer> call() throws Exception {
                throw new TestException();
            }
        })
        .test()
        .assertFailure(TestException.class);
    }

    @SuppressWarnings("unchecked")
    @Test
    public void singleCollectionSupplierReturnsNull() {
        Observable.just(1)
        .toList(new Callable<Collection<Integer>>() {
            @Override
            public Collection<Integer> call() throws Exception {
                return null;
            }
        })
        .test()
        .assertFailure(NullPointerException.class)
        .assertErrorMessage("The collectionSupplier returned a null collection. Null values are generally not allowed in 2.x operators and sources.");
    }
}


text:
<!DOCTYPE html>

		<meta charset="utf-8" />
		<base href="../../../" />

		<link type="text/css" rel="stylesheet" href="page.css" />

		[page:BufferGeometry] →

[name]

This can be used as a helper object to view a [page:Geometry Geometry] object as a wireframe.

Code Example

		var geometry = new THREE.SphereBufferGeometry( 100, 100, 100 );

		var wireframe = new THREE.WireframeGeometry( geometry );

		var line = new THREE.LineSegments( wireframe );
		line.material.depthTest = false;
		line.material.opacity = 0.25;
		line.material.transparent = true;

		scene.add( line );

Examples

			[example:webgl_helpers helpers]

Constructor

[name]( [param:Geometry geometry] )

		geometry — any geometry object.

Properties

See the base [page:BufferGeometry] class for common properties.

Methods

See the base [page:BufferGeometry] class for common methods.

Source

			[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

redpajama_set_name: RedPajamaGithub


text:
from django import forms
from django.forms.widgets import CheckboxSelectMultiple
from Materia.Turma.models import Turma
from Avaliacao.models import TemplateAvaliacao, Avaliacao
from Avaliacao.Questao.models import QuestaoDeAvaliacao, Questao ,FiltroQuestao

class criarTemplateAvaliacaoForm(forms.ModelForm):
    #titulo=forms.CharField(max_length=100)
    #data_inicio=forms.DateTimeField()
    #data_termino=forms.DateTimeField()
    #turma = forms.ModelChoiceField(queryset = Turma.objects.all(), required=True)

    class Meta:
        model = TemplateAvaliacao

    def __init__(self, *args, **kwargs):
        super(criarTemplateAvaliacaoForm, self).__init__(*args, **kwargs)
        self.fields['turma'].queryset = Turma.objects.all()

class criarFiltroQuestaoForm(forms.ModelForm):

    class Meta:
        model = FiltroQuestao
#
#    def __init__(self, *args, **kwargs):
#        super(criarFiltroQuestaoForm, self).__init__(*args, **kwargs)
#        self.fields['questaoExata'].queryset = Questao.objects.all()

    #templateAvaliacao = forms.ModelChoiceField(queryset = TemplateAvaliacao.objects.all(), required=True)
    # notaBase = forms.DecimalField(u"Nota Base",max_digits=10, decimal_places=2)
    #------- notaLimMinimo = forms.DecimalField(max_digits=10, decimal_places=2)
    #------- notaLimMaximo = forms.DecimalField(max_digits=10, decimal_places=2)
    #--- questaoExata = forms.ModelChoiceField(queryset = Questao.objects.all())


text:
define(['angular',"feed-mgr/templates/module-name"], function (angular,moduleName) {

    /**
     * Displays the page for registering a new Feed Manager template.
     *
     * @constructor
     * @param {Object} $scope the application model
     * @param {AccessControlService} AccessControlService the access control service
     * @param StateService
     */
    function RegisterNewTemplateController($scope, AccessControlService, StateService, RegisterTemplateService) {
        var self = this;

        /**
         * List of methods for registering a new template.
         *
         * @type {Array.<{name: string, description: string, icon: string, iconColor: string, onClick: function}>}
         */
        self.registrationMethods = [];

        /**
         * Creates a new Feed Manager template from a NiFi template.
         */
        self.createFromNifi = function() {
            RegisterTemplateService.resetModel();
            StateService.FeedManager().Template().navigateToRegisterNifiTemplate();
        };

        /**
         * Imports a Feed Manager template from a file.
         */
        self.importFromFile = function() {
            RegisterTemplateService.resetModel();
            StateService.FeedManager().Template().navigateToImportTemplate();
        };

        // Fetch the allowed actions
        AccessControlService.getUserAllowedActions()
		        .then(function(actionSet) {
		        	if (AccessControlService.hasAction(AccessControlService.TEMPLATES_IMPORT, actionSet.actions)) {
		        		self.registrationMethods.push({
		        			name: "Import from NiFi", description: "Import a NiFi template directly from the current environment", icon: "near_me",
		        			iconColor: "#3483BA", onClick: self.createFromNifi
		        		});
		        	}
		        });

        // Fetch the allowed actions
        AccessControlService.getUserAllowedActions()
                .then(function(actionSet) {
                    if (AccessControlService.hasAction(AccessControlService.TEMPLATES_IMPORT, actionSet.actions)) {
                        self.registrationMethods.push({
                            name: "Import from a file", description: "Import from a Kylo archive or NiFi template file", icon: "file_upload",
                            iconColor: "#F08C38", onClick: self.importFromFile
                        });
                    }
                });
    }

    angular.module(moduleName).controller("RegisterNewTemplateController",["$scope","AccessControlService","StateService","RegisterTemplateService",RegisterNewTemplateController]);
});


text:
namespace blink {

// static
ScriptPromise DataTransferItemFileSystemAccess::getAsFileSystemHandle(
    ScriptState* script_state,
    DataTransferItem& data_transfer_item) {
  if (!data_transfer_item.GetDataTransfer()->CanReadData()) {
    return ScriptPromise::CastUndefined(script_state);
  }

  // If the DataObjectItem doesn't have an associated FileSystemAccessEntry,
  // return nullptr.
  if (!data_transfer_item.GetDataObjectItem()->HasFileSystemAccessEntry()) {
    return ScriptPromise::CastUndefined(script_state);
  }

  mojo::Remote<mojom::blink::FileSystemAccessManager> fsa_manager;
  ExecutionContext* execution_context = ExecutionContext::From(script_state);
  execution_context->GetBrowserInterfaceBroker().GetInterface(
      fsa_manager.BindNewPipeAndPassReceiver());

  const DataObjectItem& data_object_item =
      *data_transfer_item.GetDataObjectItem();

  // Since tokens are move-only, we need to create a clone in order
  // to preserve the state of `data_object_item` for future calls.
  mojo::PendingRemote<mojom::blink::FileSystemAccessDataTransferToken>
      token_remote = data_object_item.CloneFileSystemAccessEntryToken();

  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
  ScriptPromise result = resolver->Promise();

  // We need to move `fsa_manager` into GetEntryFromDataTransferToken in order
  // to keep it in scope long enough for the callback to be executed. To do this
  // we extract `raw_fsa_manager` from `fsa_manager` and move `fsa_manager` into
  // the GetEntryFromDataTransferToken callback.
  auto* raw_fsa_manager = fsa_manager.get();
  raw_fsa_manager->GetEntryFromDataTransferToken(
      std::move(token_remote),
      WTF::BindOnce(
          [](mojo::Remote<mojom::blink::FileSystemAccessManager>,
             ScriptPromiseResolver* resolver,
             mojom::blink::FileSystemAccessErrorPtr result,
             mojom::blink::FileSystemAccessEntryPtr entry) {
            ScriptState* script_state = resolver->GetScriptState();
            if (!script_state)
              return;

            if (result->status != mojom::blink::FileSystemAccessStatus::kOk) {
              DCHECK(entry.is_null());
              file_system_access_error::Reject(resolver, *result);
              return;
            }

            resolver->Resolve(FileSystemHandle::CreateFromMojoEntry(
                std::move(entry), ExecutionContext::From(script_state)));
          },
          std::move(fsa_manager), WrapPersistent(resolver)));

  return result;
}

}  // namespace blink


text:
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using FaceDetection.Models;
using FaceDetection.Services;
using Newtonsoft.Json;

namespace FaceDetection.Controllers
{
    public class FaceDetectionController : ApiController
    {
        /// <summary>
        /// Posts to the Alchemy API and looks for faces.
        /// </summary>
        /// <returns>FaceDetectionResult</returns>
        public async Task<FaceDetectionResult> PostFormData()
        {
            if (!Request.Content.IsMimeMultipartContent("form-data"))
            {
                throw new HttpResponseException(HttpStatusCode.BadRequest);
            }

            var provider = await Request.Content.ReadAsMultipartAsync(new InMemoryMultipartFormDataStreamProvider());

            var files = provider.Files;
            var file1 = files[0];
            var fileStream = await file1.ReadAsStreamAsync();

            var alchemyApi = new AlchemyApi();
            return await alchemyApi.FaceDetection(fileStream);
        }

        /// <summary>
        /// Useful for a simple demonstration of the results w/o having to submit a post.
        /// </summary>
        /// <returns>FaceDetectionResult</returns>
        public async Task<FaceDetectionResult> Get()
        {
            var httpClient = new HttpClient();
            using (var content = new MultipartFormDataContent("BOUNDARY"))
            {
                var root = HttpContext.Current.Server.MapPath("~/bin");
                string path = root + "\\wade.jpg";
                var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);

                content.Add(new StreamContent(fileStream), "test", "wade.jpg");

                var request = new HttpRequestMessage
                {
                    Method = HttpMethod.Post,
                    RequestUri = new Uri("http://localhost:21346/api/facedetection"),
                    Content = content
                };

                var responseMessage = await httpClient.SendAsync(request).ConfigureAwait(false);
                var response = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);

                if (responseMessage.IsSuccessStatusCode)
                {
                    var envelope = JsonConvert.DeserializeObject<FaceDetectionResult>(response);
                    return envelope;
                }
            }

            return null;
        }
    }
}


text:
        <button id="btnNewExperiment" class="blue" ng-click="openExperimentModal()" ng-class="{disabled: !applicationsLoaded}" ng-disabled="!applicationsLoaded">Create Experiment</button>
        <input type="checkbox" id="chkToggleList" ng-model="data.showingGrid"
               ng-click="switchToGrid()" ng-class="{disabled: disableShowAsGrid}" ng-disabled="disableShowAsGrid"/>Card view

            <form id="experimentsForm">

                    <input search type="text" autocorrect="off" autocapitalize="off" placeholder="Search"
                           ng-model="data.query"
                           ng-change="search()"/>
                    Clear Search

            </form>

You have no running experiments.

 0" id="exprSummary">

{{experiment.applicationName}}

{{experiment.label}}

                         {{capitalizeFirstLetter(stateName(experiment.state))}}

                                Start

                                Pause

                                Stop

                                Delete

 0">

                            {{bucket.label}} (control)(baseline)

                                {{multiply100(bucket.actionRate) | number:1}} ±{{actionDiffForCardView(bucket) | number:1}}%
                            {{bucket.count}}

Total users:  	{{experiment.totalNumberUsers | number:0}}

 0)">

                            {{bucket.label}} {{(bucket.isControl ? ' (control)' : (bucket.isBaseLine ? ' (baseline)' : '')) }}

                                -- ±--%
                            --

Total users:  	--

                                Loading...
                                No buckets defined

 0">
            {{cardViewPageRangeStart()}} - {{cardViewPageRangeEnd()}} of {{cardViewTotalItems}}

                <uib-pagination total-items="cardViewTotalItems" items-per-page="8" ng-model="cardViewData.cardViewCurrentPage" ng-change="cardViewPageChanged()" max-size="5" rotate="false"></uib-pagination>

                    Fave

                        App

                    Experiment
                    Created By

                        Sampling %

                    Start
                    End
                    Modified

                            Status

                    Actions

                        {{experiment.applicationName}}

                        {{experiment.creatorID}}

                    {{multiply100(experiment.samplingPercent)}}
                    {{experiment.startTime | date:'MMM dd, yyyy'}}
                    {{experiment.endTime | date:'MMM dd, yyyy'}}
                    {{experiment.modificationTime | date:'MMM dd, yyyy'}}

                            Start

                            Pause

                            Stop

                            Delete

            {{pageRangeStart()}} - {{pageRangeEnd()}} of {{totalItems}}

 0">
                <uib-pagination total-items="totalItems" items-per-page="10" ng-model="currentPage" ng-change="pageChanged()" max-size="5" rotate="false"></uib-pagination>

        You are not currently authorized for any applications in the Wasabi A/B Testing system.

        If you need to be authorized for
        an existing application, please find it in the list below on the left, click on it, and then
        an email will be sent to the admins to request access.

        If you need access to a new application, please click on Create Experiment to create a new experiment.  For Application Name,
        select New Application, specify the new name of the new application, and create the experiment.  You will then be
        the admin of that new application name.

        <ng-include src="'views/AllApplicationsTable.html'"></ng-include>


text:
package mal

import (
	"fmt"
	"net/http"
	"net/http/httputil"
)

func dumpRequest(req *http.Request) {
	dump, err := httputil.DumpRequest(req, true)
	if err != nil {
		fmt.Printf("request dump failed: %s", err)
		return
	}
	fmt.Println("---------------- Request dump -----------------")
	fmt.Println(string(dump))
	fmt.Println("")
}

func dumpResponse(resp *http.Response) {
	dump, err := httputil.DumpResponse(resp, true)
	if err != nil {
		fmt.Printf("response dump failed: %s", err)
		return
	}
	fmt.Println("---------------- Response dump ----------------")
	fmt.Println(string(dump))
	fmt.Println("")
	fmt.Println("-----------------------------------------------")
}


text:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <title></title>

        Pagamento por Multibanco ou Homebanking

        Entidade:

        Referência:

        Valor:

        O talão emitido pela caixa automática faz prova de pagamento. Conserve-o.


text:
title: Tuke Street School
layout: page
date: '2013-03-13'
published: true
image: img/woodstaerial.jpg
---
The former Tuke St school site was located on Woods Road in Peckham. In 2013, the Council [resolved to sell the site](https://moderngov.southwark.gov.uk/documents/s39367/Report%20Disposal%20of%20Property%20at%20Woods%20Road%20London%20SE15.pdf) to developers Crest Nicholson. The [Cabinet report](https://moderngov.southwarksites.com/documents/s39367/Report%20Disposal%20of%20Property%20at%20Woods%20Road%20London%20SE15.pdf) approving the disposal of the site says that the site is being sold on the basis that the proposed development of 115 homes will comply with policy requirements on affordable housing:

![](https://35percent.org/img/disposalwoodsroad.png)
*Extract from the [Cabinet report](https://moderngov.southwarksites.com/documents/s39367/Report%20Disposal%20of%20Property%20at%20Woods%20Road%20London%20SE15.pdf) approving disposal of site*

In 2014, the developer applied for planning consent for 122 homes which included 35% affordable housing, but which had substituted much of the social rented element by affordable rent of up to 70% market rent. The affordable housing offer comprised just 6 social rented homes.

![](https://35percent.org/img/tukeschool.png)

Notwithstanding this and Southwark's clear [rejection of affordable rent](https://35percent.org/redefining-social-rent/) in its planning policies, Southwark's [planning committee report](https://planbuild.southwark.gov.uk/documents/?GetDocument=%7b%7b%7b!MWINWqCKxftA59dMPpEkdQ%3d%3d!%7d%7d%7d) made the baffling claim that the developer's affordable housing offer was _'broadly'_ policy compliant.

![](https://35percent.org/img/woodsroador.png)
*Extract from the [planning committee report](https://planbuild.southwark.gov.uk/documents/?GetDocument=%7b%7b%7b!MWINWqCKxftA59dMPpEkdQ%3d%3d!%7d%7d%7d)*

![](https://35percent.org/img/proudlypeckham.jpg)

Woods Road is yet another example of development on former council land which fails to provide the number of social rented homes required by policy. The land was sold on the basis of a policy-compliant development which wasn't delivered and Southwark's residents must pay the price of yet another poor deal by its political administration.

![](https://35percent.org/img/queensroad.png)
*Extract from the [S106 agreement](https://planbuild.southwark.gov.uk/documents/?GetDocument=%7b%7b%7b!JS9YMNEOEjjjL%2ff1dk3IFw%3d%3d!%7d%7d%7d) for Woods Road*


text:
VKBot поддерживает плагины, написанные на python.
Все встроенные команды реализованы через плагины. Для добавления плагина, его необходимо назвать его по образцу: `plugin_длинное_название.py`.
Если плагин назван неправильно, он не будет загружен.
При необходимости, можно заменить встроенный плагин на свой, указав такое же имя плагина (не путать с именем файла!)

## Базовый палгин
```python
# coding:utf8

class Plugin(object):
    __doc__ = """Плагин предназначен для ответа на команду.
    Для использования необходимо иметь уровень доступа {protection} или выше
    Ключевые слова: [{keywords}]
    Использование: {keyword}
    Пример: {keyword}"""

    name = 'plugin'
    keywords = (name, u'плагин')
    protection = 0
    argument_required = False

    def respond(self, msg, rsp, *args, **kwargs):
        # ваш код
        # ...
        rsp.text = u'Результат работы'

        return rsp
```

## Базовая структура плагина
Плагину необходимо иметь следующие элементы (в соответствующем порядке):
* основной класс с названием `Plugin`, к которому будет обращаться программа
* документацию
* переменную `name`, содержащую имя плагина
* переменную `keywords`, содержащую ключевые слова для вызова плагина
* переменную `protection`
* переменную `argument_required`, обозначающую, нужно ли передавать дополнительный аргумент для работы команды
* функцию `respond`

## Документация плагина
Класс плагина должен иметь переменную `__doc__`.
Рекомендация по структуре строки документации:
1 строка: `Плагин предназначен для <предназначение>.`
2 строка: `    Для использования необходимо иметь уровень доступа {protection} или выше`
3 строка: `    Ключевые слова: [{keywords}]`
4 строкк: `    Использование: {keyword} <использование>`
5 строка: `    Пример: {keyword} <пример>`

*Необходимо указать свои значения вместо объектов в угловых скобках `<>`

**Если плагин не предназначен для прямого вызова, 3, 4 и 5 строки должны иметь вид:
`    Ключевые слова: -`
`    Использование: -`
`    Пример: -`

## Переменные плагина

### name: str
Имя плагина

### keywords: tuple of str
Список клбчевых слов, при обнаружении которых будет вызван плагин

### protection: int
Если уровень доступа пользователь меньше (вызывается после функции _accept_request), команда не будет вызвана

### argument_required: bool
Если `True` и команде не передан дополнительный аргумент, функция `respond` не будет вызвана (функция `_accept_request` вызывается)

### disabled: bool
Если `True`, плагин не будет загружен. По умолчанию `False`

### priority: int
Чем выше значение, тем раньше плагин будет вызван. По умолчанию 0

## Функции плагина

### _accept_request(self, msg, rsp, utils, *args, **kwargs): bool
Вызывается до функции `respond`, возвращаемое значение определяет, будет ли вызван данный плагин. Определена по умолчанию:
```python
def _accept_request(self, msg, rsp, utils, *args, **kwargs):
    if msg.was_appeal and msg.args[0].lower() in self.keywords:
        return True

    return False
```
Обратите внимание: функция вызывается до проверки уровня доступа пользлвателя

### respond(self, msg, rsp, utils, *args, **kwargs): rsp
Принимает на вход объект сообщения msg, объект ответа rsp, объект класса дополнительных инструментов utils. (если не используется, можно не указывать явно:
`def respond(self, msg, rsp, *args, **kwargs):`
Описание передаваемых объектов приводится ниже.

Возвращает полученный объект ответа `rsp`

## Описание передаваемых объектов

### msg

Объект, сообщения, имеющий следующие переменные:

#### raw_text: str
Текст полученного сообщения (без изменений)

#### lower_text: str
`raw_text` в нижнем регистре

#### text: str
`raw_text` с вырезанным обращением(если было)

#### args: tuple of str
Список слов из `raw_text` (разделён пробелами)

#### was_appeal: bool
`True`, если было оращение к боту

#### from_user: bool
`True`, если сообщение пришло от пользователя

#### from_chat: bool
`True`, если сообщение пришло из беседы

#### from_group: bool
`True`, если сообщение пришло от группы

#### user_id: int
id диалога с пользователем (если `from_user`)

#### real_user_id: int
id автора сообщения (если `from_user` или `from_chat`)

#### chat_id: int
id беседы, из которой пришло сообщение (если `from_chat`)

#### chat_users: list of int
Список id пользователей беседы (если `from_chat`)

#### chat_name: str
Название беседы (если `from_chat`)

#### out: bool
`True`, если сообщение отправлено со страницы владельца бота

#### event_user_id: int
Поле `action_mid` полученного сообщения

#### event_text: str
Поле `action_text` полученного сообщения

#### msg_id: int
id полученного сообщения

***

### rsp
Объект ответа, имеющий следующие переменные:

#### target: int
Сообщение будет отправлено на этот id

#### sticker: int
id стикера, который необзодимо прикрепить

#### text: str
Текст сообщения, который необходимо отправить

#### do_mark: bool
Если `True`, сообщение будет отмечено (в соответствии с соответствующей опцией)

#### forward_msg: int
id сообщения, которое необходимо переслать

#### send():
Функция позволяет моментально отправить сообщение с текущими параметрами

***

### utils
Объект, содержащий вспомогательные функции и переменные:

#### get_settings(keys, section='Plugins'): dict
Читает файл настроек и возвращает значения.
Возврщает словарь `{key: value}`, если keys является кортежем или списком, иначе возвращается только значение
Возращает None, если данного ключа/секции не существует.

#### set_setting(key, value, section='Plugins'):
Устанавливает/создаёт значение ключа и сохраняет файл конфига.

#### get_blacklist(): dict
Возращает словарь заблокированных id: `{id(str): 'Причина'}`

#### get_whitelist(): dict
Возвращает словарь id с повышенным доступом `{id(str): уровень(int)}`

#### get_custom_commands(): dict
Возвращает словарь пользовательских команд. Структура словаря:

```python
{
    'команда 1':
        ['ответ 1', 0, 0, 0, 0, 0],
        ['ответ 2', 0, 0, 0, 0, 0]
    'команда 2':
        ...
}

# 2-6 элементы ответа - опции, стоящие в позиции 0, 1 или 2
(1 существует не для всех)
```

#### save_setting(key, val, section='General'):
Функция сохраняет настройку `key` со значением `val` в секции конфига `General`

#### save_blacklist(blacklist):
Функия сохраняет словарь id с повышенным доступом (структура описана выше)

#### save_whitelist(whitelist):
Функия сохраняет словарь заблокированных id (структура описана выше)

#### save_custom_commands(custom_commands):
Функия сохраняет словарь пользовательских команд (структура описана выше)

#### clear_message_queue():
Функция заставляет бота забыть пришедшие к нему сообщения (если такие были)

#### get_user_access_level(msg): int
Возвращает уровень доступа пользователя

#### safe_format(text, *args, **kwargs): str
Функция форматирует строку, пропуская отсутствующие ключи

#### get_plugin_list(): list of str
Возвращает список загруженных плагинов (отсортированы в порядке приоритета)

#### get_builtin_plugin_list(): list of str
Возвращает список загруженных встроенных плагинов (не отсортированы)

#### get_custom_plugin_list(): list of str
Возвращает список загруженных пользовательских плагинов (не отсортированы)

#### get_plugin(name): plugin object
Возвращает объект плагина по имени

#### stop_bot():
Останавливает бота (сначала будет отправлено сообщение, возвращённое функцией `respond`)

#### restart_bot():
Перезапускает бота (сначала будет отправлено сообщение, возвращённое функцией `respond`)

#### set_startup_response(rsp):
Позволяет установить сообщение, которое будет отправлено сразу после выполнения
функции `restart_bot`

#### log(message, importance, t=time.time()):
Функция предназначена для отправки сообщений в панель логов на главном экране приложения.
Принимает параметры `message` (str), `importance` (int) (от 0 до 3)

#### vkr
TODO


text:
{% load i18n %}

        {% trans "LAN" %}
        {% trans "Competition" %}
        {% trans "Type" %}
        {% trans "Status" %}

        {% for competition in competitions %}

            {{ competition.lan }}
            {{ competition }}
            {% if competition.use_teams %}
            {% trans "Team" %}
            {% else %}
            {% trans "Solo" %}
            {% endif %}
            {{ competition.status_text }}

        {% endfor %}


text:
import tensorflow.compat.v2 as tf
import numpy as np
import typing

def create_mlp(
    input_dim,
    output_dim,
    hidden_dims = (256, 256),
    activation = tf.nn.relu,
    last_layer_activation = None,
    near_zero_last_layer = False,
):
  """Creates an MLP.

  Args:
    input_dim: input dimensionaloty.
    output_dim: output dimensionality.
    hidden_dims: hidden layers dimensionality.
    activation: activations after hidden units.

  Returns:
    An MLP model.
  """
  if not hasattr(input_dim, '__len__'):
    input_dim = [input_dim]
  initialization = tf.keras.initializers.VarianceScaling(
      scale=0.333, mode='fan_in', distribution='uniform')
  near_zero_initialization = tf.keras.initializers.VarianceScaling(
      scale=1e-2, mode='fan_in', distribution='uniform')

  layers = []
  for hidden_dim in hidden_dims:
    layers.append(
        tf.keras.layers.Dense(
            hidden_dim,
            activation=activation,
            #kernel_initializer=initialization
        ))
  layers += [
      tf.keras.layers.Dense(
          output_dim,
          activation=last_layer_activation,
          #kernel_initializer=near_zero_initialization
          #if near_zero_last_layer else initialization
      )
  ]

  inputs = tf.keras.Input(shape=input_dim)
  outputs = tf.keras.Sequential(layers)(inputs)

  model = tf.keras.Model(inputs=inputs, outputs=outputs)
  model.call = tf.function(model.call)
  return model

def create_conv(
    input_shape,
    kernel_sizes = (2, 2, 3),
    stride_sizes = (1, 1, 2),
    pool_sizes = None,
    num_filters = 64,
    activation = tf.nn.relu,
    activation_last_layer = True,
    output_dim = None,
    padding = 'same',
    residual=False,
):
  """Creates an MLP.

  Args:
    input_shape: input shape.
    hidden_dims: hidden layers dimensionality.
    activation: activations after hidden units.

  Returns:
    An MLP model.
  """
  if not hasattr(num_filters, '__len__'):
    num_filters = (num_filters,) * len(kernel_sizes)
  if not hasattr(pool_sizes, '__len__'):
    pool_sizes = (pool_sizes,) * len(kernel_sizes)

  layers = []
  for i, (kernel_size, stride, filters, pool_size) in enumerate(
      zip(kernel_sizes, stride_sizes, num_filters, pool_sizes)):
    if i == len(kernel_sizes) - 1 and not output_dim:
      activation = activation if activation_last_layer else None
    layers.append(
        tf.keras.layers.Conv2D(
            filters,
            kernel_size,
            strides=(stride, stride),
            activation=activation,
            padding=padding))
    if pool_size:
      layers.append(
          tf.keras.layers.MaxPool2D(pool_size=pool_size, padding=padding))

  if output_dim:
    layers += [
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(
            output_dim,
            activation=activation if activation_last_layer else None)
    ]

  inputs = tf.keras.Input(shape=input_shape)
  if residual:
    outputs = layers[0](inputs)
    for layer in layers[1:-1]:
      outputs = outputs + layer(outputs)
    outputs = layers[-1](outputs)
  else:
    outputs = tf.keras.Sequential(layers)(inputs)

  model = tf.keras.Model(inputs=inputs, outputs=outputs)
  model.call = tf.function(model.call)
  return model

def create_rnn(
    input_dims,
    output_dim = None,
    hidden_dims = (256,),
    activation = tf.nn.relu,
    bidirectional=True,
):
  inputs = tf.keras.Input(shape=input_dims)
  if bidirectional:
    layers = [
        tf.keras.layers.Bidirectional(
            tf.keras.layers.LSTM(hidden_dim, return_sequences=True))
        for hidden_dim in hidden_dims
    ]
  else:
    layers = [
        tf.keras.layers.LSTM(hidden_dim, return_sequences=True)
        for hidden_dim in hidden_dims
    ]

  outputs = tf.keras.Sequential(layers)(inputs)
  if output_dim:
    outputs = tf.keras.Sequential([
        tf.keras.layers.Lambda(lambda x: tf.reduce_max(x, axis=1)),
        tf.keras.layers.Dense(output_dim)
    ])(
        outputs)

  model = tf.keras.Model(inputs=inputs, outputs=outputs)
  model.call = tf.function(model.call)
  return model

def convert_to_tf_dataset(dataset,
                          max_trajectory_length,
                          batch_size,
                          pos_only=False):
  states, next_states, actions, rewards = [], [], [], []
  episodes, valid_steps = dataset.get_all_episodes()
  for episode_num in range(tf.shape(valid_steps)[0]):
    episode_states, episode_next_states, episode_actions, episode_rewards = [], [], [], []
    keep = False
    for step_num in range(tf.shape(valid_steps)[1] - 1):
      this_step = tf.nest.map_structure(lambda t: t[episode_num, step_num],
                                        episodes)
      next_step = tf.nest.map_structure(lambda t: t[episode_num, step_num + 1],
                                        episodes)
      if this_step.is_last() or not valid_steps[episode_num, step_num]:
        continue

      keep = keep or this_step.reward > 0
      episode_states.append(this_step.observation)
      episode_next_states.append(next_step.observation)
      episode_actions.append(this_step.action)
      episode_rewards.append(this_step.reward)
    if not keep and pos_only:
      continue
    states.append(episode_states)
    next_states.append(episode_next_states)
    actions.append(episode_actions)
    rewards.append(episode_rewards)

  states = tf.keras.preprocessing.sequence.pad_sequences(
      states,
      maxlen=max_trajectory_length,
      padding='post',
      dtype=np.int32,
      value=-1)
  next_states = tf.keras.preprocessing.sequence.pad_sequences(
      next_states,
      maxlen=max_trajectory_length,
      padding='post',
      dtype=np.int32,
      value=-1)
  actions = tf.keras.preprocessing.sequence.pad_sequences(
      actions,
      maxlen=max_trajectory_length,
      padding='post',
      dtype=np.int32,
      value=-1)
  rewards = tf.keras.preprocessing.sequence.pad_sequences(
      rewards,
      maxlen=max_trajectory_length,
      padding='post',
      dtype=np.float32,
      value=-1)
  mask = tf.cast(rewards >= 0, tf.float32)

  dataset = tf.data.Dataset.from_tensor_slices(
      (states, actions, rewards, next_states, mask)).cache().shuffle(
          states.shape[0], reshuffle_each_iteration=True).repeat().batch(
              batch_size,
              drop_remainder=True).prefetch(tf.data.experimental.AUTOTUNE)
  return dataset

def convert_to_np_dataset(dataset, tabular_obs=False, tabular_act=False):
  dataset_spec = dataset.spec
  observation_spec = dataset_spec.observation
  action_spec = dataset_spec.action
  num_states = observation_spec.maximum + 1
  num_actions = action_spec.maximum + 1
  trajectories = []
  episodes, valid_steps = dataset.get_all_episodes()
  for episode_num in range(tf.shape(valid_steps)[0]):
    episode_states, episode_next_states, episode_actions, episode_rewards, episode_dones = [], [], [], [], []
    for step_num in range(tf.shape(valid_steps)[1] - 1):
      this_step = tf.nest.map_structure(lambda t: t[episode_num, step_num],
                                        episodes)
      next_step = tf.nest.map_structure(lambda t: t[episode_num, step_num + 1],
                                        episodes)
      episode_states.append(
          tf.one_hot(this_step.observation, num_states
                    ) if tabular_obs else this_step.observation)
      episode_next_states.append(
          tf.one_hot(next_step.observation, num_states
                    ) if tabular_obs else next_step.observation)
      episode_actions.append(
          tf.one_hot(this_step.action, num_actions
                    ) if tabular_act else this_step.action)
      reward = this_step.reward * tf.cast(
          not this_step.is_last() and valid_steps[episode_num, step_num],
          tf.float32)
      episode_rewards.append(reward)
      episode_dones.append(this_step.is_last() or
                           not valid_steps[episode_num, step_num])
    trajectory = {
        'observations': np.array(episode_states, dtype=np.float32),
        'actions': np.array(episode_actions, dtype=np.float32),
        'rewards': np.array(episode_rewards, dtype=np.float32),
        'dones': np.array(episode_dones, dtype=np.float32)
    }
    trajectories.append(trajectory)
  return trajectories

def transformer_module(query,
                       value,
                       key,
                       embedding_dim=256,
                       num_heads=4,
                       key_dim=128,
                       ff_dim=256,
                       rate=0.1,
                       output_dim=None,
                       last_layer=False,
                       attention_mask=None):
  """From https://keras.io/examples/nlp/masked_language_modeling/"""
  # Multi headed self-attention
  attention_output, attention_scores = tf.keras.layers.MultiHeadAttention(
      num_heads=num_heads, key_dim=key_dim)(
          query,
          value,
          key=key,
          attention_mask=attention_mask,
          return_attention_scores=True)
  attention_output = tf.keras.layers.Dropout(rate)(attention_output)
  attention_output = tf.keras.layers.LayerNormalization(
      epsilon=1e-6,)(
          query + attention_output)

  # Feed-forward layer
  ffn = tf.keras.Sequential([
      tf.keras.layers.Dense(ff_dim, activation='relu'),
      tf.keras.layers.Dense(output_dim or embedding_dim),
  ],)
  ffn_output = ffn(attention_output)

  if last_layer:
    sequence_output = ffn_output
  else:
    ffn_output = tf.keras.layers.Dropout(rate)(ffn_output)
    sequence_output = tf.keras.layers.LayerNormalization(epsilon=1e-6)(
        attention_output + ffn_output)

  return sequence_output, attention_scores

def transformer(embeddings,
                num_layers=4,
                embedding_dim=256,
                num_heads=4,
                key_dim=64,
                ff_dim=256,
                rate=0.,
                output_dim=None,
                attention_mask=None):
  output_dim = output_dim or embedding_dim
  encoder_output = embeddings

  for i in range(num_layers):
    last_layer = i == num_layers - 1
    encoder_output, attention_scores = transformer_module(
        encoder_output,
        encoder_output,
        encoder_output,
        embedding_dim=embedding_dim,
        num_heads=num_heads,
        key_dim=key_dim,
        ff_dim=ff_dim,
        output_dim=output_dim if last_layer else None,
        last_layer=last_layer,
        rate=rate,
        attention_mask=attention_mask)
  return encoder_output

def dense_gaussian_kl(mu_left, logvar_left, mu_right, logvar_right):
  gauss_klds = 0.5 * (
      logvar_right - logvar_left +
      (tf.exp(logvar_left) / tf.exp(logvar_right)) +
      ((mu_left - mu_right)**2.0 / tf.exp(logvar_right)) - 1.0)
  return gauss_klds

def dense_cross_entropy(logits, labels):
  """Applies sparse cross entropy loss between logits and target labels."""
  loss = -labels * tf.math.log(tf.nn.softmax(logits, axis=-1) + 1e-8)
  return loss

def accuracy(logits, labels):
  """Applies sparse cross entropy loss between logits and target labels."""
  predicted_label = tf.argmax(logits, axis=-1)
  acc = tf.cast(tf.equal(predicted_label, labels), tf.float32)
  return tf.reduce_mean(acc)

def to_categorical(obs, num_classes):
  b, w, _ = obs.shape
  flat_obs = obs.reshape(-1).copy()
  one_hot = np.zeros((b * w * w, num_classes))
  one_hot[np.arange(b * w * w), flat_obs] = 1
  return one_hot.reshape(
      (obs.shape[0], obs.shape[1], obs.shape[2], num_classes)).astype(np.uint8)


text:
public class Extracted<T> {
    public T myT;

    public Extracted() {
    }
}


text:
package uk.gov.gchq.gaffer.rest.integration.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;

import uk.gov.gchq.gaffer.cache.impl.HashMapCacheService;
import uk.gov.gchq.gaffer.commonutil.StreamUtil;
import uk.gov.gchq.gaffer.core.exception.Error;
import uk.gov.gchq.gaffer.data.element.Entity;
import uk.gov.gchq.gaffer.federatedstore.operation.GetAllGraphIds;
import uk.gov.gchq.gaffer.graph.Graph;
import uk.gov.gchq.gaffer.graph.GraphConfig;
import uk.gov.gchq.gaffer.mapstore.MapStoreProperties;
import uk.gov.gchq.gaffer.operation.impl.add.AddElements;
import uk.gov.gchq.gaffer.operation.impl.get.GetAllElements;
import uk.gov.gchq.gaffer.operation.impl.job.GetAllJobDetails;
import uk.gov.gchq.gaffer.rest.factory.GraphFactory;
import uk.gov.gchq.gaffer.rest.factory.MockGraphFactory;
import uk.gov.gchq.gaffer.store.Context;
import uk.gov.gchq.gaffer.store.StoreProperties;
import uk.gov.gchq.gaffer.store.schema.Schema;
import uk.gov.gchq.gaffer.store.schema.SchemaEntityDefinition;
import uk.gov.gchq.gaffer.store.schema.TypeDefinition;
import uk.gov.gchq.koryphe.impl.binaryoperator.StringConcat;

import java.io.IOException;
import java.util.Set;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;
import static uk.gov.gchq.gaffer.cache.util.CacheProperties.CACHE_SERVICE_CLASS;
import static uk.gov.gchq.gaffer.core.exception.Status.SERVICE_UNAVAILABLE;
import static uk.gov.gchq.gaffer.jsonserialisation.JSONSerialiser.createDefaultMapper;

public class OperationControllerIT extends AbstractRestApiIT {

    @Autowired
    private GraphFactory graphFactory; // This will be a Mock (see application-test.properties)

    private MockGraphFactory getGraphFactory() {
        return (MockGraphFactory) graphFactory;
    }

    @Test
    public void shouldReturnHelpfulErrorMessageIfJsonIsIncorrect() {
        // Given
        Graph graph = new Graph.Builder()
                .config(StreamUtil.graphConfig(this.getClass()))
                .storeProperties(new MapStoreProperties())
                .addSchema(new Schema())
                .build();

        when(getGraphFactory().getGraph()).thenReturn(graph);

        // When
        String request = "{\"class\"\"GetAllElements\"}";

        LinkedMultiValueMap headers = new LinkedMultiValueMap();
        headers.add("Content-Type", "application/json;charset=utf-8");

        final ResponseEntity<Error> response = post("/graph/operations/execute",
                new HttpEntity(request, headers),
                Error.class);

        // Then
        assertEquals(400, response.getStatusCode().value());
        assertEquals(400, response.getBody().getStatusCode());
        assertTrue(response.getBody().getSimpleMessage().contains("was expecting a colon to separate field name and value"));
    }

    @Test
    public void shouldReturnHelpfulErrorMessageIfOperationIsUnsupported() {
        // Given
        Graph graph = new Graph.Builder()
            .config(StreamUtil.graphConfig(this.getClass()))
            .storeProperties(new MapStoreProperties())
            .addSchema(new Schema())
            .build();

        when(getGraphFactory().getGraph()).thenReturn(graph);

        // When
        final ResponseEntity<Error> response = post("/graph/operations/execute",
            new GetAllGraphIds(),
            Error.class);

        // Then

        assertNotNull(response.getBody().getSimpleMessage());
        assertTrue(response.getBody().getSimpleMessage().contains("GetAllGraphIds is not supported by the MapStore"));
    }

    @Test
    public void shouldReturn403WhenUnauthorised() throws IOException {
        // Given
        Graph graph = new Graph.Builder()
                .config(StreamUtil.graphConfig(this.getClass()))
                .storeProperties(new MapStoreProperties())
                .addSchema(new Schema())
                .build();

        when(getGraphFactory().getGraph()).thenReturn(graph);

        // When
        final ResponseEntity<Error> response = post("/graph/operations/execute",
                new GetAllElements(),
                Error.class);

        // Then
        assertEquals(403, response.getStatusCode().value());
        assertEquals(403, response.getBody().getStatusCode());
    }

    @Test
    public void shouldPropagateStatusInformationContainedInOperationExceptionsThrownByOperationHandlers() throws IOException {
        // Given
        final StoreProperties storeProperties = new MapStoreProperties();
        storeProperties.set(StoreProperties.JOB_TRACKER_ENABLED, Boolean.FALSE.toString());

        final Graph graph = new Graph.Builder()
                .config(StreamUtil.graphConfig(this.getClass()))
                .storeProperties(storeProperties)
                .addSchema(new Schema())
                .build();

        when(getGraphFactory().getGraph()).thenReturn(graph);

        // When
        final ResponseEntity<Error> response = post("/graph/operations/execute",
                new GetAllJobDetails(),
                Error.class);
        // Then
        assertEquals(SERVICE_UNAVAILABLE.getStatusCode(), response.getStatusCode().value());
    }

    @Test
    public void shouldReturnSameJobIdInHeaderAsGetAllJobDetailsOperation() throws IOException {
        // Given
        StoreProperties properties = new MapStoreProperties();
        properties.setJobTrackerEnabled(true);
        properties.set(CACHE_SERVICE_CLASS, HashMapCacheService.class.getName());

        Graph graph = new Graph.Builder()
                .config(StreamUtil.graphConfig(this.getClass()))
                .storeProperties(properties)
                .addSchema(new Schema())
                .build();

        when(getGraphFactory().getGraph()).thenReturn(graph);

        // When
        final ResponseEntity<Set> response = post("/graph/operations/execute",
                new GetAllJobDetails(),
                Set.class);

        // Then
        try {
            assertTrue(response.getBody().toString().contains(response.getHeaders().get("job-id").get(0)));
        } catch (final AssertionError e) {
            System.out.println("Job ID was not found in the Header");
            System.out.println("Header was: " + response.getHeaders().get("job-id"));
            System.out.println("Body was: " + response.getBody());
            throw e;
        }
    }

    @Test
    public void shouldCorrectlyStreamExecuteChunked() throws Exception {
        // Given
        final Schema schema =  new Schema.Builder()
                .entity("g1", new SchemaEntityDefinition.Builder()
                        .vertex("string")
                        .build())
                .type("string", new TypeDefinition.Builder()
                        .clazz(String.class)
                        .aggregateFunction(new StringConcat())
                        .build())
                .build();

        Graph graph = new Graph.Builder()
                .config(new GraphConfig("id"))
                .storeProperties(new MapStoreProperties())
                .addSchema(schema)
                .build();

        when(getGraphFactory().getGraph()).thenReturn(graph);

        Entity ent1 = new Entity.Builder()
                .group("g1")
                .vertex("v1")
                .build();

        Entity ent2 = new Entity.Builder()
                .group("g1")
                .vertex("v2")
                .build();

        final ObjectMapper mapper = createDefaultMapper();

        graph.execute(new AddElements.Builder()
                .input(ent1)
                .build(), new Context());

        graph.execute(new AddElements.Builder()
                .input(ent2)
                .build(), new Context());

        // When
        final ResponseEntity<String> response = post("/graph/operations/execute/chunked",
                new GetAllElements.Builder()
                .build(),
                String.class);

        // Then
        String expected = mapper.writeValueAsString(ent1) + "\r\n" + mapper.writeValueAsString(ent2) + "\r\n";
        assertEquals(expected, response.getBody());
    }
}


text:
// File Name: reportLocalWaypointMessage.c
//
// Written By: Danny Kent (jaus AT dannykent DOT com), Tom Galluzzo (galluzzo AT gmail DOT com)
//
// Version: 3.3.0b
//
// Date: 09/08/09
//
// Description: This file defines the functionality of a ReportLocalWaypointMessage

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jaus.h"

static const int commandCode = JAUS_REPORT_LOCAL_WAYPOINT;
static const int maxDataSizeBytes = 21;

static JausBoolean headerFromBuffer(ReportLocalWaypointMessage message, unsigned char *buffer, unsigned int bufferSizeBytes);
static JausBoolean headerToBuffer(ReportLocalWaypointMessage message, unsigned char *buffer, unsigned int bufferSizeBytes);
static int headerToString(ReportLocalWaypointMessage message, char **buf);

static JausBoolean dataFromBuffer(ReportLocalWaypointMessage message, unsigned char *buffer, unsigned int bufferSizeBytes);
static int dataToBuffer(ReportLocalWaypointMessage message, unsigned char *buffer, unsigned int bufferSizeBytes);
static void dataInitialize(ReportLocalWaypointMessage message);
static unsigned int dataSize(ReportLocalWaypointMessage message);

// ************************************************************************************************************** //
//                                    USER CONFIGURED FUNCTIONS
// ************************************************************************************************************** //

// Initializes the message-specific fields
static void dataInitialize(ReportLocalWaypointMessage message)
{
	// Report initial values of message fields
	message->presenceVector = newJausByte(JAUS_BYTE_PRESENCE_VECTOR_ALL_ON);
	message->waypointNumber = newJausUnsignedShort(0);
	message->xM = newJausDouble(0);		// Scaled Integer (-100000, 100000)
	message->yM = newJausDouble(0); 	// Scaled Integer (-100000, 100000)
	message->zM = newJausDouble(0); 	// Scaled Integer (-10000, 35000)
	message->rollRadians = newJausDouble(0);		// Scaled Short (-JAUS_PI, JAUS_PI)
	message->pitchRadians = newJausDouble(0);		// Scaled Short (-JAUS_PI, JAUS_PI)
	message->yawRadians = newJausDouble(0);			// Scaled Short (-JAUS_PI, JAUS_PI)
}

// Return boolean of success
static JausBoolean dataFromBuffer(ReportLocalWaypointMessage message, unsigned char *buffer, unsigned int bufferSizeBytes)
{
	int index = 0;
	JausInteger tempInteger;
	JausShort tempShort;

	if(bufferSizeBytes == message->dataSize)
	{
		// Unpack Message Fields from Buffer
		// Use Presence Vector
		if(!jausByteFromBuffer(&message->presenceVector, buffer+index, bufferSizeBytes-index)) return JAUS_FALSE;
		index += JAUS_BYTE_SIZE_BYTES;

		if(!jausUnsignedShortFromBuffer(&message->waypointNumber, buffer+index, bufferSizeBytes-index)) return JAUS_FALSE;
		index += JAUS_UNSIGNED_SHORT_SIZE_BYTES;

		//unpack
		//JausDouble xM		// Scaled Integer (-100000, 100000)
		if(!jausIntegerFromBuffer(&tempInteger, buffer+index, bufferSizeBytes-index)) return JAUS_FALSE;
		index += JAUS_INTEGER_SIZE_BYTES;
		message->xM = jausIntegerToDouble(tempInteger, -100000, 100000);

		//unpack
		//JausDouble yM		// Scaled Integer (-100000, 100000)
		if(!jausIntegerFromBuffer(&tempInteger, buffer+index, bufferSizeBytes-index)) return JAUS_FALSE;
		index += JAUS_INTEGER_SIZE_BYTES;
		message->yM = jausIntegerToDouble(tempInteger, -100000, 100000);

		if(jausByteIsBitSet(message->presenceVector, JAUS_LOCAL_WAYPOINT_PV_Z_BIT))
		{
			//unpack
			//JausDouble zM	// Scaled Integer (-10000, 35000)
			if(!jausIntegerFromBuffer(&tempInteger, buffer+index, bufferSizeBytes-index)) return JAUS_FALSE;
			index += JAUS_INTEGER_SIZE_BYTES;

			message->zM = jausIntegerToDouble(tempInteger, -10000, 35000);
		}

		if(jausByteIsBitSet(message->presenceVector, JAUS_LOCAL_WAYPOINT_PV_ROLL_BIT))
		{
			//unpack
			//JausDouble rollRadians // Scaled Short (-JAUS_PI, JAUS_PI)
			if(!jausShortFromBuffer(&tempShort, buffer+index, bufferSizeBytes-index)) return JAUS_FALSE;
			index += JAUS_SHORT_SIZE_BYTES;

			message->rollRadians = jausShortToDouble(tempShort, -JAUS_PI, JAUS_PI);
		}

		if(jausByteIsBitSet(message->presenceVector, JAUS_LOCAL_WAYPOINT_PV_PITCH_BIT))
		{
			//unpack
			//JausDouble pitchRadians;		// Scaled Short (-JAUS_PI, JAUS_PI)
			if(!jausShortFromBuffer(&tempShort, buffer+index, bufferSizeBytes-index)) return JAUS_FALSE;
			index += JAUS_SHORT_SIZE_BYTES;

			message->pitchRadians = jausShortToDouble(tempShort, -JAUS_PI, JAUS_PI);
		}

		if(jausByteIsBitSet(message->presenceVector, JAUS_LOCAL_WAYPOINT_PV_YAW_BIT))
		{
			//unpack
			//JausDouble yawRadians;			// Scaled Short (-JAUS_PI, JAUS_PI)
			if(!jausShortFromBuffer(&tempShort, buffer+index, bufferSizeBytes-index)) return JAUS_FALSE;
			index += JAUS_SHORT_SIZE_BYTES;

			message->yawRadians = jausShortToDouble(tempShort, -JAUS_PI, JAUS_PI);
		}
		return JAUS_TRUE;
	}
	else
	{
		return JAUS_FALSE;
	}
}

// Returns number of bytes put into the buffer
static int dataToBuffer(ReportLocalWaypointMessage message, unsigned char *buffer, unsigned int bufferSizeBytes)
{
	int index = 0;
	JausInteger tempInteger;
	JausShort tempShort;

	if(bufferSizeBytes >= dataSize(message))
	{
		// Pack Message Fields to Buffer
		// Use Presence Vector
		if(!jausByteToBuffer(message->presenceVector, buffer+index, bufferSizeBytes-index)) return JAUS_FALSE;
		index += JAUS_BYTE_SIZE_BYTES;

		if(!jausUnsignedShortToBuffer(message->waypointNumber, buffer+index, bufferSizeBytes-index)) return JAUS_FALSE;
		index += JAUS_UNSIGNED_SHORT_SIZE_BYTES;

		//pack
		//JausDouble xM		// Scaled Integer (-100000, 100000)
		tempInteger = jausIntegerFromDouble(message->xM, -100000, 100000);
		if(!jausIntegerToBuffer(tempInteger, buffer+index, bufferSizeBytes-index)) return JAUS_FALSE;
		index += JAUS_INTEGER_SIZE_BYTES;

		//pack
		//JausDouble yM		// Scaled Integer (-100000, 100000)
		tempInteger = jausIntegerFromDouble(message->yM, -100000, 100000);
		if(!jausIntegerToBuffer(tempInteger, buffer+index, bufferSizeBytes-index)) return JAUS_FALSE;
		index += JAUS_INTEGER_SIZE_BYTES;

		if(jausByteIsBitSet(message->presenceVector, JAUS_LOCAL_WAYPOINT_PV_Z_BIT))
		{
			//pack
			//JausDouble zM	// Scaled Integer (-10000, 35000)
			tempInteger = jausIntegerFromDouble(message->zM, -10000, 35000);
			if(!jausIntegerToBuffer(tempInteger, buffer+index, bufferSizeBytes-index)) return JAUS_FALSE;
			index += JAUS_INTEGER_SIZE_BYTES;
		}

		if(jausByteIsBitSet(message->presenceVector, JAUS_LOCAL_WAYPOINT_PV_ROLL_BIT))
		{
			//pack
			//JausDouble rollRadians // Scaled Short (-JAUS_PI, JAUS_PI)
			tempShort = jausShortFromDouble(message->rollRadians, -JAUS_PI, JAUS_PI);
			if(!jausShortToBuffer(tempShort, buffer+index, bufferSizeBytes-index)) return JAUS_FALSE;
			index += JAUS_SHORT_SIZE_BYTES;
		}

		if(jausByteIsBitSet(message->presenceVector, JAUS_LOCAL_WAYPOINT_PV_PITCH_BIT))
		{
			//pack
			//JausDouble pitchRadians;		// Scaled Short (-JAUS_PI, JAUS_PI)
			tempShort = jausShortFromDouble(message->pitchRadians, -JAUS_PI, JAUS_PI);
			if(!jausShortToBuffer(tempShort, buffer+index, bufferSizeBytes-index)) return JAUS_FALSE;
			index += JAUS_SHORT_SIZE_BYTES;
		}

		if(jausByteIsBitSet(message->presenceVector, JAUS_LOCAL_WAYPOINT_PV_YAW_BIT))
		{
			//pack
			//JausDouble yawRadians;			// Scaled Short (-JAUS_PI, JAUS_PI)
			tempShort = jausShortFromDouble(message->yawRadians, -JAUS_PI, JAUS_PI);
			if(!jausShortToBuffer(tempShort, buffer+index, bufferSizeBytes-index)) return JAUS_FALSE;
			index += JAUS_SHORT_SIZE_BYTES;
		}
	}
	return index;
}

static int dataToString(ReportLocalWaypointMessage message, char **buf)
{
  //message already verified

  //Setup temporary string buffer

  unsigned int bufSize = 400;
  (*buf) = (char*)malloc(sizeof(char)*bufSize);

  strcpy((*buf), "\nPresence Vector: " );
  jausByteToHexString(message->presenceVector, (*buf)+strlen(*buf));

  strcat((*buf), "\nWaypoint Number: ");
  jausUnsignedShortToString(message->waypointNumber, (*buf)+strlen(*buf));

  strcat((*buf), "\nX(meters): ");
  jausDoubleToString(message->xM, (*buf)+strlen(*buf));

  strcat((*buf), "\nY(meters): ");
  jausDoubleToString(message->yM, (*buf)+strlen(*buf));

  if(jausByteIsBitSet(message->presenceVector, JAUS_LOCAL_WAYPOINT_PV_Z_BIT))
  {
    strcat((*buf), "\nZ(meters): ");
    jausDoubleToString(message->zM, (*buf)+strlen(*buf));
  }

  if(jausByteIsBitSet(message->presenceVector, JAUS_LOCAL_WAYPOINT_PV_ROLL_BIT))
  {
    strcat((*buf), "\nRoll(radians): ");
    jausDoubleToString(message->rollRadians, (*buf)+strlen(*buf));
  }

  if(jausByteIsBitSet(message->presenceVector, JAUS_LOCAL_WAYPOINT_PV_PITCH_BIT))
  {
    strcat((*buf), "\nPitch(radians): ");
    jausDoubleToString(message->pitchRadians, (*buf)+strlen(*buf));
  }

  if(jausByteIsBitSet(message->presenceVector, JAUS_LOCAL_WAYPOINT_PV_YAW_BIT))
  {
    strcat((*buf), "\nYaw(radians): ");
    jausDoubleToString(message->yawRadians, (*buf)+strlen(*buf));
  }
  return (int)strlen(*buf);
}

static unsigned int dataSize(ReportLocalWaypointMessage message)
{
	int index = 0;

	index += JAUS_BYTE_SIZE_BYTES;

	index += JAUS_UNSIGNED_SHORT_SIZE_BYTES;

	index += JAUS_INTEGER_SIZE_BYTES;

	index += JAUS_INTEGER_SIZE_BYTES;

	if(jausByteIsBitSet(message->presenceVector, JAUS_LOCAL_WAYPOINT_PV_Z_BIT))
	{
		index += JAUS_INTEGER_SIZE_BYTES;
	}

	if(jausByteIsBitSet(message->presenceVector, JAUS_LOCAL_WAYPOINT_PV_ROLL_BIT))
	{
		index += JAUS_SHORT_SIZE_BYTES;
	}

	if(jausByteIsBitSet(message->presenceVector, JAUS_LOCAL_WAYPOINT_PV_PITCH_BIT))
	{
		index += JAUS_SHORT_SIZE_BYTES;
	}

	if(jausByteIsBitSet(message->presenceVector, JAUS_LOCAL_WAYPOINT_PV_YAW_BIT))
	{
		index += JAUS_SHORT_SIZE_BYTES;
	}

	return index;
}

// ************************************************************************************************************** //
//                                    NON-USER CONFIGURED FUNCTIONS
// ************************************************************************************************************** //

ReportLocalWaypointMessage reportLocalWaypointMessageCreate(void)
{
	ReportLocalWaypointMessage message;

	message = (ReportLocalWaypointMessage)malloc( sizeof(ReportLocalWaypointMessageStruct) );
	if(message == NULL)
	{
		return NULL;
	}

	// Initialize Values
	message->properties.priority = JAUS_DEFAULT_PRIORITY;
	message->properties.ackNak = JAUS_ACK_NAK_NOT_REQUIRED;
	message->properties.scFlag = JAUS_NOT_SERVICE_CONNECTION_MESSAGE;
	message->properties.expFlag = JAUS_NOT_EXPERIMENTAL_MESSAGE;
	message->properties.version = JAUS_VERSION_3_3;
	message->properties.reserved = 0;
	message->commandCode = commandCode;
	message->destination = jausAddressCreate();
	message->source = jausAddressCreate();
	message->dataFlag = JAUS_SINGLE_DATA_PACKET;
	message->dataSize = maxDataSizeBytes;
	message->sequenceNumber = 0;

	dataInitialize(message);
	message->dataSize = dataSize(message);

	return message;
}

void reportLocalWaypointMessageDestroy(ReportLocalWaypointMessage message)
{
	jausAddressDestroy(message->source);
	jausAddressDestroy(message->destination);
	free(message);
}

JausBoolean reportLocalWaypointMessageFromBuffer(ReportLocalWaypointMessage message, unsigned char* buffer, unsigned int bufferSizeBytes)
{
	int index = 0;

	if(headerFromBuffer(message, buffer+index, bufferSizeBytes-index))
	{
		index += JAUS_HEADER_SIZE_BYTES;
		if(dataFromBuffer(message, buffer+index, bufferSizeBytes-index))
		{
			return JAUS_TRUE;
		}
		else
		{
			return JAUS_FALSE;
		}
	}
	else
	{
		return JAUS_FALSE;
	}
}

JausBoolean reportLocalWaypointMessageToBuffer(ReportLocalWaypointMessage message, unsigned char *buffer, unsigned int bufferSizeBytes)
{
	if(bufferSizeBytes < reportLocalWaypointMessageSize(message))
	{
		return JAUS_FALSE; //improper size
	}
	else
	{
		message->dataSize = dataToBuffer(message, buffer+JAUS_HEADER_SIZE_BYTES, bufferSizeBytes - JAUS_HEADER_SIZE_BYTES);
		if(headerToBuffer(message, buffer, bufferSizeBytes))
		{
			return JAUS_TRUE;
		}
		else
		{
			return JAUS_FALSE; // headerToReportLocalWaypointBuffer failed
		}
	}
}

ReportLocalWaypointMessage reportLocalWaypointMessageFromJausMessage(JausMessage jausMessage)
{
	ReportLocalWaypointMessage message;

	if(jausMessage->commandCode != commandCode)
	{
		return NULL; // Wrong message type
	}
	else
	{
		message = (ReportLocalWaypointMessage)malloc( sizeof(ReportLocalWaypointMessageStruct) );
		if(message == NULL)
		{
			return NULL;
		}

		message->properties.priority = jausMessage->properties.priority;
		message->properties.ackNak = jausMessage->properties.ackNak;
		message->properties.scFlag = jausMessage->properties.scFlag;
		message->properties.expFlag = jausMessage->properties.expFlag;
		message->properties.version = jausMessage->properties.version;
		message->properties.reserved = jausMessage->properties.reserved;
		message->commandCode = jausMessage->commandCode;
		message->destination = jausAddressCreate();
		*message->destination = *jausMessage->destination;
		message->source = jausAddressCreate();
		*message->source = *jausMessage->source;
		message->dataSize = jausMessage->dataSize;
		message->dataFlag = jausMessage->dataFlag;
		message->sequenceNumber = jausMessage->sequenceNumber;

		// Unpack jausMessage->data
		if(dataFromBuffer(message, jausMessage->data, jausMessage->dataSize))
		{
			return message;
		}
		else
		{
			return NULL;
		}
	}
}

JausMessage reportLocalWaypointMessageToJausMessage(ReportLocalWaypointMessage message)
{
	JausMessage jausMessage;

	jausMessage = (JausMessage)malloc( sizeof(struct JausMessageStruct) );
	if(jausMessage == NULL)
	{
		return NULL;
	}

	jausMessage->properties.priority = message->properties.priority;
	jausMessage->properties.ackNak = message->properties.ackNak;
	jausMessage->properties.scFlag = message->properties.scFlag;
	jausMessage->properties.expFlag = message->properties.expFlag;
	jausMessage->properties.version = message->properties.version;
	jausMessage->properties.reserved = message->properties.reserved;
	jausMessage->commandCode = message->commandCode;
	jausMessage->destination = jausAddressCreate();
	*jausMessage->destination = *message->destination;
	jausMessage->source = jausAddressCreate();
	*jausMessage->source = *message->source;
	jausMessage->dataSize = dataSize(message);
	jausMessage->dataFlag = message->dataFlag;
	jausMessage->sequenceNumber = message->sequenceNumber;

	jausMessage->data = (unsigned char *)malloc(jausMessage->dataSize);
	jausMessage->dataSize = dataToBuffer(message, jausMessage->data, jausMessage->dataSize);

	return jausMessage;
}

unsigned int reportLocalWaypointMessageSize(ReportLocalWaypointMessage message)
{
	return (unsigned int)(dataSize(message) + JAUS_HEADER_SIZE_BYTES);
}

char* reportLocalWaypointMessageToString(ReportLocalWaypointMessage message)
{
  if(message)
  {
    char* buf1 = NULL;
    char* buf2 = NULL;
    char* buf = NULL;

    int returnVal;

    //Print the message header to the string buffer
    returnVal = headerToString(message, &buf1);

    //Print the message data fields to the string buffer
    returnVal += dataToString(message, &buf2);

buf = (char*)malloc(strlen(buf1)+strlen(buf2)+1);
    strcpy(buf, buf1);
    strcat(buf, buf2);

    free(buf1);
    free(buf2);

    return buf;
  }
  else
  {
    char* buf = "Invalid ReportLocalWaypoint Message";
    char* msg = (char*)malloc(strlen(buf)+1);
    strcpy(msg, buf);
    return msg;
  }
}
//********************* PRIVATE HEADER FUNCTIONS **********************//

static JausBoolean headerFromBuffer(ReportLocalWaypointMessage message, unsigned char *buffer, unsigned int bufferSizeBytes)
{
	if(bufferSizeBytes < JAUS_HEADER_SIZE_BYTES)
	{
		return JAUS_FALSE;
	}
	else
	{
		// unpack header
		message->properties.priority = (buffer[0] & 0x0F);
		message->properties.ackNak	 = ((buffer[0] >> 4) & 0x03);
		message->properties.scFlag	 = ((buffer[0] >> 6) & 0x01);
		message->properties.expFlag	 = ((buffer[0] >> 7) & 0x01);
		message->properties.version	 = (buffer[1] & 0x3F);
		message->properties.reserved = ((buffer[1] >> 6) & 0x03);

		message->commandCode = buffer[2] + (buffer[3] << 8);

		message->destination->instance = buffer[4];
		message->destination->component = buffer[5];
		message->destination->node = buffer[6];
		message->destination->subsystem = buffer[7];

		message->source->instance = buffer[8];
		message->source->component = buffer[9];
		message->source->node = buffer[10];
		message->source->subsystem = buffer[11];

		message->dataSize = buffer[12] + ((buffer[13] & 0x0F) << 8);

		message->dataFlag = ((buffer[13] >> 4) & 0x0F);

		message->sequenceNumber = buffer[14] + (buffer[15] << 8);

		return JAUS_TRUE;
	}
}

static JausBoolean headerToBuffer(ReportLocalWaypointMessage message, unsigned char *buffer, unsigned int bufferSizeBytes)
{
	JausUnsignedShort *propertiesPtr = (JausUnsignedShort*)&message->properties;

	if(bufferSizeBytes < JAUS_HEADER_SIZE_BYTES)
	{
		return JAUS_FALSE;
	}
	else
	{
		buffer[0] = (unsigned char)(*propertiesPtr & 0xFF);
		buffer[1] = (unsigned char)((*propertiesPtr & 0xFF00) >> 8);

		buffer[2] = (unsigned char)(message->commandCode & 0xFF);
		buffer[3] = (unsigned char)((message->commandCode & 0xFF00) >> 8);

		buffer[4] = (unsigned char)(message->destination->instance & 0xFF);
		buffer[5] = (unsigned char)(message->destination->component & 0xFF);
		buffer[6] = (unsigned char)(message->destination->node & 0xFF);
		buffer[7] = (unsigned char)(message->destination->subsystem & 0xFF);

		buffer[8] = (unsigned char)(message->source->instance & 0xFF);
		buffer[9] = (unsigned char)(message->source->component & 0xFF);
		buffer[10] = (unsigned char)(message->source->node & 0xFF);
		buffer[11] = (unsigned char)(message->source->subsystem & 0xFF);

		buffer[12] = (unsigned char)(message->dataSize & 0xFF);
		buffer[13] = (unsigned char)((message->dataFlag & 0xFF) << 4) | (unsigned char)((message->dataSize & 0x0F00) >> 8);

		buffer[14] = (unsigned char)(message->sequenceNumber & 0xFF);
		buffer[15] = (unsigned char)((message->sequenceNumber & 0xFF00) >> 8);

		return JAUS_TRUE;
	}
}

static int headerToString(ReportLocalWaypointMessage message, char **buf)
{
  //message existance already verified

  //Setup temporary string buffer

  unsigned int bufSize = 500;
  (*buf) = (char*)malloc(sizeof(char)*bufSize);

  strcpy((*buf), jausCommandCodeString(message->commandCode) );
  strcat((*buf), " (0x");
  sprintf((*buf)+strlen(*buf), "%04X", message->commandCode);

  strcat((*buf), ")\nReserved: ");
  jausUnsignedShortToString(message->properties.reserved, (*buf)+strlen(*buf));

  strcat((*buf), "\nVersion: ");
  switch(message->properties.version)
  {
    case 0:
      strcat((*buf), "2.0 and 2.1 compatible");
      break;
    case 1:
      strcat((*buf), "3.0 through 3.1 compatible");
      break;
    case 2:
      strcat((*buf), "3.2 and 3.3 compatible");
      break;
    default:
      strcat((*buf), "Reserved for Future: ");
      jausUnsignedShortToString(message->properties.version, (*buf)+strlen(*buf));
      break;
  }

  strcat((*buf), "\nExp. Flag: ");
  if(message->properties.expFlag == 0)
    strcat((*buf), "Not Experimental");
  else
    strcat((*buf), "Experimental");

  strcat((*buf), "\nSC Flag: ");
  if(message->properties.scFlag == 1)
    strcat((*buf), "Service Connection");
  else
    strcat((*buf), "Not Service Connection");

  strcat((*buf), "\nACK/NAK: ");
  switch(message->properties.ackNak)
  {
  case 0:
    strcat((*buf), "None");
    break;
  case 1:
    strcat((*buf), "Request ack/nak");
    break;
  case 2:
    strcat((*buf), "nak response");
    break;
  case 3:
    strcat((*buf), "ack response");
    break;
  default:
    break;
  }

  strcat((*buf), "\nPriority: ");
  if(message->properties.priority < 12)
  {
    strcat((*buf), "Normal Priority ");
    jausUnsignedShortToString(message->properties.priority, (*buf)+strlen(*buf));
  }
  else
  {
    strcat((*buf), "Safety Critical Priority ");
    jausUnsignedShortToString(message->properties.priority, (*buf)+strlen(*buf));
  }

  strcat((*buf), "\nSource: ");
  jausAddressToString(message->source, (*buf)+strlen(*buf));

  strcat((*buf), "\nDestination: ");
  jausAddressToString(message->destination, (*buf)+strlen(*buf));

  strcat((*buf), "\nData Size: ");
  jausUnsignedIntegerToString(message->dataSize, (*buf)+strlen(*buf));

  strcat((*buf), "\nData Flag: ");
  jausUnsignedIntegerToString(message->dataFlag, (*buf)+strlen(*buf));
  switch(message->dataFlag)
  {
    case 0:
      strcat((*buf), " Only data packet in single-packet stream");
      break;
    case 1:
      strcat((*buf), " First data packet in muti-packet stream");
      break;
    case 2:
      strcat((*buf), " Normal data packet");
      break;
    case 4:
      strcat((*buf), " Retransmitted data packet");
      break;
    case 8:
      strcat((*buf), " Last data packet in stream");
      break;
    default:
      strcat((*buf), " Unrecognized data flag code");
      break;
  }

  strcat((*buf), "\nSequence Number: ");
  jausUnsignedShortToString(message->sequenceNumber, (*buf)+strlen(*buf));

  return (int)strlen(*buf);

}


text:
/*
 * File: Extras.js
 *
 * Provides Extras such as Tips and Style Effects.
 *
 * Description:
 *
 * Provides the <Tips> and <NodeStyles> classes and functions.
 *
 */

/*
 * Manager for mouse events (clicking and mouse moving).
 *
 * This class is used for registering objects implementing onClick
 * and onMousemove methods. These methods are called when clicking or
 * moving the mouse around  the Canvas.
 * For now, <Tips> and <NodeStyles> are classes implementing these methods.
 *
 */
var ExtrasInitializer = {
  initialize: function(className, viz) {
    this.viz = viz;
    this.canvas = viz.canvas;
    this.config = viz.config[className];
    this.nodeTypes = viz.fx.nodeTypes;
    var type = this.config.type;
    this.dom = type == 'auto'? (viz.config.Label.type != 'Native') : (type != 'Native');
    this.labelContainer = this.dom && viz.labels.getLabelContainer();
    this.isEnabled() && this.initializePost();
  },
  initializePost: $.empty,
  setAsProperty: $.lambda(false),
  isEnabled: function() {
    return this.config.enable;
  },
  isLabel: function(e, win, group) {
    e = $.event.get(e, win);
    var labelContainer = this.labelContainer,
        target = e.target || e.srcElement,
        related = e.relatedTarget;
    if(group) {
      return related && related == this.viz.canvas.getCtx().canvas
          && !!target && this.isDescendantOf(target, labelContainer);
    } else {
      return this.isDescendantOf(target, labelContainer);
    }
  },
  isDescendantOf: function(elem, par) {
    while(elem && elem.parentNode) {
      if(elem.parentNode == par)
        return elem;
      elem = elem.parentNode;
    }
    return false;
  }
};

var EventsInterface = {
  onMouseUp: $.empty,
  onMouseDown: $.empty,
  onMouseMove: $.empty,
  onMouseOver: $.empty,
  onMouseOut: $.empty,
  onMouseWheel: $.empty,
  onTouchStart: $.empty,
  onTouchMove: $.empty,
  onTouchEnd: $.empty,
  onTouchCancel: $.empty
};

var MouseEventsManager = new Class({
  initialize: function(viz) {
    this.viz = viz;
    this.canvas = viz.canvas;
    this.node = false;
    this.edge = false;
    this.registeredObjects = [];
    this.attachEvents();
  },

  attachEvents: function() {
    var htmlCanvas = this.canvas.getElement(),
        that = this;
    htmlCanvas.oncontextmenu = $.lambda(false);
    $.addEvents(htmlCanvas, {
      'mouseup': function(e, win) {
        var event = $.event.get(e, win);
        that.handleEvent('MouseUp', e, win,
            that.makeEventObject(e, win),
            $.event.isRightClick(event));
      },
      'mousedown': function(e, win) {
        var event = $.event.get(e, win);
        that.handleEvent('MouseDown', e, win, that.makeEventObject(e, win),
            $.event.isRightClick(event));
      },
      'mousemove': function(e, win) {
        that.handleEvent('MouseMove', e, win, that.makeEventObject(e, win));
      },
      'mouseover': function(e, win) {
        that.handleEvent('MouseOver', e, win, that.makeEventObject(e, win));
      },
      'mouseout': function(e, win) {
        that.handleEvent('MouseOut', e, win, that.makeEventObject(e, win));
      },
      'touchstart': function(e, win) {
        that.handleEvent('TouchStart', e, win, that.makeEventObject(e, win));
      },
      'touchmove': function(e, win) {
        that.handleEvent('TouchMove', e, win, that.makeEventObject(e, win));
      },
      'touchend': function(e, win) {
        that.handleEvent('TouchEnd', e, win, that.makeEventObject(e, win));
      }
    });
    //attach mousewheel event
    var handleMouseWheel = function(e, win) {
      var event = $.event.get(e, win);
      var wheel = $.event.getWheel(event);
      that.handleEvent('MouseWheel', e, win, wheel);
    };
    //TODO(nico): this is a horrible check for non-gecko browsers!
    if(!document.getBoxObjectFor && window.mozInnerScreenX == null) {
      $.addEvent(htmlCanvas, 'mousewheel', handleMouseWheel);
    } else {
      htmlCanvas.addEventListener('DOMMouseScroll', handleMouseWheel, false);
    }
  },

  register: function(obj) {
    this.registeredObjects.push(obj);
  },

  handleEvent: function() {
    var args = Array.prototype.slice.call(arguments),
        type = args.shift();
    for(var i=0, regs=this.registeredObjects, l=regs.length; i<l; i++) {
      regs[i]['on' + type].apply(regs[i], args);
    }
  },

  makeEventObject: function(e, win) {
    var that = this,
        graph = this.viz.graph,
        fx = this.viz.fx,
        ntypes = fx.nodeTypes,
        etypes = fx.edgeTypes;
    return {
      pos: false,
      node: false,
      edge: false,
      contains: false,
      getNodeCalled: false,
      getEdgeCalled: false,
      getPos: function() {
        //TODO(nico): check why this can't be cache anymore when using edge detection
        //if(this.pos) return this.pos;
        var canvas = that.viz.canvas,
            s = canvas.getSize(),
            p = canvas.getPos(),
            ox = canvas.translateOffsetX,
            oy = canvas.translateOffsetY,
            sx = canvas.scaleOffsetX,
            sy = canvas.scaleOffsetY,
            pos = $.event.getPos(e, win);
        this.pos = {
          x: (pos.x - p.x - s.width/2 - ox) * 1/sx,
          y: (pos.y - p.y - s.height/2 - oy) * 1/sy
        };
        return this.pos;
      },
      getNode: function() {
        if(this.getNodeCalled) return this.node;
        this.getNodeCalled = true;
        for(var id in graph.nodes) {
          var n = graph.nodes[id],
              geom = n && ntypes[n.getData('type')],
              contains = geom && geom.contains && geom.contains.call(fx, n, this.getPos());
          if(contains) {
            this.contains = contains;
            return that.node = this.node = n;
          }
        }
        return that.node = this.node = false;
      },
      getEdge: function() {
        if(this.getEdgeCalled) return this.edge;
        this.getEdgeCalled = true;
        var hashset = {};
        for(var id in graph.edges) {
          var edgeFrom = graph.edges[id];
          hashset[id] = true;
          for(var edgeId in edgeFrom) {
            if(edgeId in hashset) continue;
            var e = edgeFrom[edgeId],
                geom = e && etypes[e.getData('type')],
                contains = geom && geom.contains && geom.contains.call(fx, e, this.getPos());
            if(contains) {
              this.contains = contains;
              return that.edge = this.edge = e;
            }
          }
        }
        return that.edge = this.edge = false;
      },
      getContains: function() {
        if(this.getNodeCalled) return this.contains;
        this.getNode();
        return this.contains;
      }
    };
  }
});

/*
 * Provides the initialization function for <NodeStyles> and <Tips> implemented
 * by all main visualizations.
 *
 */
var Extras = {
  initializeExtras: function() {
    var mem = new MouseEventsManager(this), that = this;
    $.each(['NodeStyles', 'Tips', 'Navigation', 'Events'], function(k) {
      var obj = new Extras.Classes[k](k, that);
      if(obj.isEnabled()) {
        mem.register(obj);
      }
      if(obj.setAsProperty()) {
        that[k.toLowerCase()] = obj;
      }
    });
  }
};

Extras.Classes = {};
/*
  Class: Events

  This class defines an Event API to be accessed by the user.
  The methods implemented are the ones defined in the <Options.Events> object.
*/

Extras.Classes.Events = new Class({
  Implements: [ExtrasInitializer, EventsInterface],

  initializePost: function() {
    this.fx = this.viz.fx;
    this.ntypes = this.viz.fx.nodeTypes;
    this.etypes = this.viz.fx.edgeTypes;

    this.hovered = false;
    this.pressed = false;
    this.touched = false;

    this.touchMoved = false;
    this.moved = false;

  },

  setAsProperty: $.lambda(true),

  onMouseUp: function(e, win, event, isRightClick) {
    var evt = $.event.get(e, win);
    if(!this.moved) {
      if(isRightClick) {
        this.hovered && this.config.onRightClick(this.hovered, event, evt);
      } else {
        this.pressed && this.config.onClick(this.pressed, event, evt);
      }
    }
    if(this.pressed) {
      if(this.moved) {
        this.config.onDragEnd(this.pressed, event, evt);
      } else {
        this.config.onDragCancel(this.pressed, event, evt);
      }
      this.pressed = this.moved = false;
    }
  },

  onMouseOut: function(e, win, event) {
   //mouseout a label
   var evt = $.event.get(e, win), label;
   if(this.dom && (label = this.isLabel(e, win, true))) {
     this.config.onMouseLeave(this.viz.graph.getNode(label.id),
                              event, evt);
     this.hovered = false;
     return;
   }
   //mouseout canvas
   var rt = evt.relatedTarget,
       canvasWidget = this.canvas.getElement();
   while(rt && rt.parentNode) {
     if(canvasWidget == rt.parentNode) return;
     rt = rt.parentNode;
   }
   if(this.hovered) {
     this.config.onMouseLeave(this.hovered,
         event, evt);
     this.hovered = false;
   }
  },

  onMouseOver: function(e, win, event) {
    //mouseover a label
    var evt = $.event.get(e, win), label;
    if(this.dom && (label = this.isLabel(e, win, true))) {
      this.hovered = this.viz.graph.getNode(label.id);
      this.config.onMouseEnter(this.hovered,
                               event, evt);
    }
  },

  onMouseMove: function(e, win, event) {
   var label, evt = $.event.get(e, win);
   if(this.pressed) {
     this.moved = true;
     this.config.onDragMove(this.pressed, event, evt);
     return;
   }
   if(this.dom) {
     this.config.onMouseMove(this.hovered,
         event, evt);
   } else {
     if(this.hovered) {
       var hn = this.hovered;
       var geom = hn.nodeFrom? this.etypes[hn.getData('type')] : this.ntypes[hn.getData('type')];
       var contains = geom && geom.contains
         && geom.contains.call(this.fx, hn, event.getPos());
       if(contains) {
         this.config.onMouseMove(hn, event, evt);
         return;
       } else {
         this.config.onMouseLeave(hn, event, evt);
         this.hovered = false;
       }
     }
     if(this.hovered = (event.getNode() || (this.config.enableForEdges && event.getEdge()))) {
       this.config.onMouseEnter(this.hovered, event, evt);
     } else {
       this.config.onMouseMove(false, event, evt);
     }
   }
  },

  onMouseWheel: function(e, win, delta) {
    this.config.onMouseWheel(delta, $.event.get(e, win));
  },

  onMouseDown: function(e, win, event) {
    var evt = $.event.get(e, win), label;
    if(this.dom) {
      if(label = this.isLabel(e, win)) {
        this.pressed = this.viz.graph.getNode(label.id);
      }
    } else {
      this.pressed = event.getNode() || (this.config.enableForEdges && event.getEdge());
    }
    this.pressed && this.config.onDragStart(this.pressed, event, evt);
  },

  onTouchStart: function(e, win, event) {
    var evt = $.event.get(e, win), label;
    if(this.dom && (label = this.isLabel(e, win))) {
      this.touched = this.viz.graph.getNode(label.id);
    } else {
      this.touched = event.getNode() || (this.config.enableForEdges && event.getEdge());
    }
    this.touched && this.config.onTouchStart(this.touched, event, evt);
  },

  onTouchMove: function(e, win, event) {
    var evt = $.event.get(e, win);
    if(this.touched) {
      this.touchMoved = true;
      this.config.onTouchMove(this.touched, event, evt);
    }
  },

  onTouchEnd: function(e, win, event) {
    var evt = $.event.get(e, win);
    if(this.touched) {
      if(this.touchMoved) {
        this.config.onTouchEnd(this.touched, event, evt);
      } else {
        this.config.onTouchCancel(this.touched, event, evt);
      }
      this.touched = this.touchMoved = false;
    }
  }
});

/*
   Class: Tips

   A class containing tip related functions. This class is used internally.

   Used by:

   <ST>, <Sunburst>, <Hypertree>, <RGraph>, <TM>, <ForceDirected>, <Icicle>

   See also:

   <Options.Tips>
*/

Extras.Classes.Tips = new Class({
  Implements: [ExtrasInitializer, EventsInterface],

  initializePost: function() {
    //add DOM tooltip
    if(document.body) {
      var tip = $('_tooltip') || document.createElement('div');
      tip.id = '_tooltip';
      tip.className = 'tip';
      $.extend(tip.style, {
        position: 'absolute',
        display: 'none',
        zIndex: 13000
      });
      document.body.appendChild(tip);
      this.tip = tip;
      this.node = false;
    }
  },

  setAsProperty: $.lambda(true),

  onMouseOut: function(e, win) {
    //mouseout a label
    var evt = $.event.get(e, win);
    if(this.dom && this.isLabel(e, win, true)) {
      this.hide(true);
      return;
    }
    //mouseout canvas
    var rt = e.relatedTarget,
        canvasWidget = this.canvas.getElement();
    while(rt && rt.parentNode) {
      if(canvasWidget == rt.parentNode) return;
      rt = rt.parentNode;
    }
    this.hide(false);
  },

  onMouseOver: function(e, win) {
    //mouseover a label
    var label;
    if(this.dom && (label = this.isLabel(e, win, true))) {
      this.node = this.viz.graph.getNode(label.id);
      this.config.onShow(this.tip, this.node, label);
    }
  },

  onMouseMove: function(e, win, opt) {
    if(this.dom && this.isLabel(e, win)) {
      this.setTooltipPosition($.event.getPos(e, win));
    }
    if(!this.dom) {
      var node = opt.getNode();
      if(!node) {
        this.hide(true);
        return;
      }
      if(this.config.force || !this.node || this.node.id != node.id) {
        this.node = node;
        this.config.onShow(this.tip, node, opt.getContains());
      }
      this.setTooltipPosition($.event.getPos(e, win));
    }
  },

  setTooltipPosition: function(pos) {
    var tip = this.tip,
        style = tip.style,
        cont = this.config;
    style.display = '';
    //get window dimensions
    var win = {
      'height': document.body.clientHeight,
      'width': document.body.clientWidth
    };
    //get tooltip dimensions
    var obj = {
      'width': tip.offsetWidth,
      'height': tip.offsetHeight
    };
    //set tooltip position
    var x = cont.offsetX, y = cont.offsetY;
    style.top = ((pos.y + y + obj.height > win.height)?
        (pos.y - obj.height - y) : pos.y + y) + 'px';
    style.left = ((pos.x + obj.width + x > win.width)?
        (pos.x - obj.width - x) : pos.x + x) + 'px';
  },

  hide: function(triggerCallback) {
    this.tip.style.display = 'none';
    triggerCallback && this.config.onHide();
  }
});

/*
  Class: NodeStyles

  Change node styles when clicking or hovering a node. This class is used internally.

  Used by:

  <ST>, <Sunburst>, <Hypertree>, <RGraph>, <TM>, <ForceDirected>, <Icicle>

  See also:

  <Options.NodeStyles>
*/
Extras.Classes.NodeStyles = new Class({
  Implements: [ExtrasInitializer, EventsInterface],

  initializePost: function() {
    this.fx = this.viz.fx;
    this.types = this.viz.fx.nodeTypes;
    this.nStyles = this.config;
    this.nodeStylesOnHover = this.nStyles.stylesHover;
    this.nodeStylesOnClick = this.nStyles.stylesClick;
    this.hoveredNode = false;
    this.fx.nodeFxAnimation = new Animation();

    this.down = false;
    this.move = false;
  },

  onMouseOut: function(e, win) {
    this.down = this.move = false;
    if(!this.hoveredNode) return;
    //mouseout a label
    if(this.dom && this.isLabel(e, win, true)) {
      this.toggleStylesOnHover(this.hoveredNode, false);
    }
    //mouseout canvas
    var rt = e.relatedTarget,
        canvasWidget = this.canvas.getElement();
    while(rt && rt.parentNode) {
      if(canvasWidget == rt.parentNode) return;
      rt = rt.parentNode;
    }
    this.toggleStylesOnHover(this.hoveredNode, false);
    this.hoveredNode = false;
  },

  onMouseOver: function(e, win) {
    //mouseover a label
    var label;
    if(this.dom && (label = this.isLabel(e, win, true))) {
      var node = this.viz.graph.getNode(label.id);
      if(node.selected) return;
      this.hoveredNode = node;
      this.toggleStylesOnHover(this.hoveredNode, true);
    }
  },

  onMouseDown: function(e, win, event, isRightClick) {
    if(isRightClick) return;
    var label;
    if(this.dom && (label = this.isLabel(e, win))) {
      this.down = this.viz.graph.getNode(label.id);
    } else if(!this.dom) {
      this.down = event.getNode();
    }
    this.move = false;
  },

  onMouseUp: function(e, win, event, isRightClick) {
    if(isRightClick) return;
    if(!this.move) {
      this.onClick(event.getNode());
    }
    this.down = this.move = false;
  },

  getRestoredStyles: function(node, type) {
    var restoredStyles = {},
        nStyles = this['nodeStylesOn' + type];
    for(var prop in nStyles) {
      restoredStyles[prop] = node.styles['$' + prop];
    }
    return restoredStyles;
  },

  toggleStylesOnHover: function(node, set) {
    if(this.nodeStylesOnHover) {
      this.toggleStylesOn('Hover', node, set);
    }
  },

  toggleStylesOnClick: function(node, set) {
    if(this.nodeStylesOnClick) {
      this.toggleStylesOn('Click', node, set);
    }
  },

  toggleStylesOn: function(type, node, set) {
    var viz = this.viz;
    var nStyles = this.nStyles;
    if(set) {
      var that = this;
      if(!node.styles) {
        node.styles = $.merge(node.data, {});
      }
      for(var s in this['nodeStylesOn' + type]) {
        var $s = '$' + s;
        if(!($s in node.styles)) {
            node.styles[$s] = node.getData(s);
        }
      }
      viz.fx.nodeFx($.extend({
        'elements': {
          'id': node.id,
          'properties': that['nodeStylesOn' + type]
         },
         transition: Trans.Quart.easeOut,
         duration:300,
         fps:40
      }, this.config));
    } else {
      var restoredStyles = this.getRestoredStyles(node, type);
      viz.fx.nodeFx($.extend({
        'elements': {
          'id': node.id,
          'properties': restoredStyles
         },
         transition: Trans.Quart.easeOut,
         duration:300,
         fps:40
      }, this.config));
    }
  },

  onClick: function(node) {
    if(!node) return;
    var nStyles = this.nodeStylesOnClick;
    if(!nStyles) return;
    //if the node is selected then unselect it
    if(node.selected) {
      this.toggleStylesOnClick(node, false);
      delete node.selected;
    } else {
      //unselect all selected nodes...
      this.viz.graph.eachNode(function(n) {
        if(n.selected) {
          for(var s in nStyles) {
            n.setData(s, n.styles['$' + s], 'end');
          }
          delete n.selected;
        }
      });
      //select clicked node
      this.toggleStylesOnClick(node, true);
      node.selected = true;
      delete node.hovered;
      this.hoveredNode = false;
    }
  },

  onMouseMove: function(e, win, event) {
    //if mouse button is down and moving set move=true
    if(this.down) this.move = true;
    //already handled by mouseover/out
    if(this.dom && this.isLabel(e, win)) return;
    var nStyles = this.nodeStylesOnHover;
    if(!nStyles) return;

    if(!this.dom) {
      if(this.hoveredNode) {
        var geom = this.types[this.hoveredNode.getData('type')];
        var contains = geom && geom.contains && geom.contains.call(this.fx,
            this.hoveredNode, event.getPos());
        if(contains) return;
      }
      var node = event.getNode();
      //if no node is being hovered then just exit
      if(!this.hoveredNode && !node) return;
      //if the node is hovered then exit
      if(node.hovered) return;
      //select hovered node
      if(node && !node.selected) {
        //check if an animation is running and exit it
        this.fx.nodeFxAnimation.stopTimer();
        //unselect all hovered nodes...
        this.viz.graph.eachNode(function(n) {
          if(n.hovered && !n.selected) {
            for(var s in nStyles) {
              n.setData(s, n.styles['$' + s], 'end');
            }
            delete n.hovered;
          }
        });
        //select hovered node
        node.hovered = true;
        this.hoveredNode = node;
        this.toggleStylesOnHover(node, true);
      } else if(this.hoveredNode && !this.hoveredNode.selected) {
        //check if an animation is running and exit it
        this.fx.nodeFxAnimation.stopTimer();
        //unselect hovered node
        this.toggleStylesOnHover(this.hoveredNode, false);
        delete this.hoveredNode.hovered;
        this.hoveredNode = false;
      }
    }
  }
});

Extras.Classes.Navigation = new Class({
  Implements: [ExtrasInitializer, EventsInterface],

  initializePost: function() {
    this.pos = false;
    this.pressed = false;
  },

  onMouseWheel: function(e, win, scroll) {
    if(!this.config.zooming) return;
    $.event.stop($.event.get(e, win));
    var val = this.config.zooming / 1000,
        ans = 1 + scroll * val;
    this.canvas.scale(ans, ans);
  },

  onMouseDown: function(e, win, eventInfo) {
    if(!this.config.panning) return;
    if(this.config.panning == 'avoid nodes' && (this.dom? this.isLabel(e, win) : eventInfo.getNode())) return;
    this.pressed = true;
    this.pos = eventInfo.getPos();
    var canvas = this.canvas,
        ox = canvas.translateOffsetX,
        oy = canvas.translateOffsetY,
        sx = canvas.scaleOffsetX,
        sy = canvas.scaleOffsetY;
    this.pos.x *= sx;
    this.pos.x += ox;
    this.pos.y *= sy;
    this.pos.y += oy;
  },

  onMouseMove: function(e, win, eventInfo) {
    if(!this.config.panning) return;
    if(!this.pressed) return;
    if(this.config.panning == 'avoid nodes' && (this.dom? this.isLabel(e, win) : eventInfo.getNode())) return;
    var thispos = this.pos,
        currentPos = eventInfo.getPos(),
        canvas = this.canvas,
        ox = canvas.translateOffsetX,
        oy = canvas.translateOffsetY,
        sx = canvas.scaleOffsetX,
        sy = canvas.scaleOffsetY;
    currentPos.x *= sx;
    currentPos.y *= sy;
    currentPos.x += ox;
    currentPos.y += oy;
    var x = currentPos.x - thispos.x,
        y = currentPos.y - thispos.y;
    this.pos = currentPos;
    this.canvas.translate(x * 1/sx, y * 1/sy);
  },

  onMouseUp: function(e, win, eventInfo, isRightClick) {
    if(!this.config.panning) return;
    this.pressed = false;
  }
});


text:
<?php
// destroy
require_once(__DIR__.'/connect.php');
require_once(__DIR__.'/push.php');

$data = json_decode($_REQUEST['data'], true);

$id = (integer) $data['id'];

$query = "delete from products where id = $id;";

$db->exec($query);

//push
$aNotification = array(
	'xtype' => 'productsgrid',
	'event' => 'productdel',
	'params' => array(
        'id' => $id
	)
);
push($aNotification);


text:
require 'chefspec'

describe 'gem_package::upgrade' do
  let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) }

  it 'upgrades a gem_package with an explicit action' do
    expect(chef_run).to upgrade_gem_package('explicit_action')
    expect(chef_run).to_not upgrade_gem_package('not_explicit_action')
  end

  it 'upgrades a gem_package with attributes' do
    expect(chef_run).to upgrade_gem_package('with_attributes').with(version: '1.0.0')
    expect(chef_run).to_not upgrade_gem_package('with_attributes').with(version: '1.2.3')
  end

  it 'upgrades a gem_package when specifying the identity attribute' do
    expect(chef_run).to upgrade_gem_package('identity_attribute')
  end
end