text:
This page describes various extra details of the Skia Gold service
that the GPU pixel tests use. For information on running the tests locally, see
[this section][local pixel testing]. For common information on triaging,
modification, or general pixel wrangling, see [GPU Pixel Wrangling] or these
sections ([1][pixel debugging], [2][pixel updating]) of the general GPU testing
documentation.

[local pixel testing]: gpu_testing.md#Running-the-pixel-tests-locally
[GPU Pixel Wrangling]: http://go/gpu-pixel-wrangler
[pixel debugging]: gpu_testing.md#Debugging-Pixel-Test-Failures-on-the-GPU-Bots
[pixel updating]: gpu_testing.md#Updating-and-Adding-New-Pixel-Tests-to-the-GPU-Bots

[TOC]

## Skia Gold

[Gold][gold documentation] is an image diff service developed by the Skia team.
It was originally developed solely for Skia's usage and only supported
post-submit tests, but has been picked up by other projects such as Chromium and
PDFium and now supports trybots. Unlike other image diff solutions in Chromium,
comparisons are done in an external service instead of locally on the testing
machine.

[gold documentation]: https://skia.org/dev/testing/skiagold

### Why Gold

Gold has three main advantages over the traditional local image comparison
historically used by Chromium:

1. Triage time can be much lower. Because triaging is handled by an external
service, new golden images don't need to go through the CQ and wait for
waterfall bots to pick up the CL. Once an image is triaged in Gold, it
becomes immediately available for future test runs.
2. Gold supports multiple approved images per test. It is not uncommon for
tests to produce images that are visually indistinguishable, but differ in
a handful of pixels by a small RGB value. Fuzzy image diffing can solve this
problem, but introduces its own set of issues such as possibly causing a test
to erroneously pass. Since most tests that exhibit this behavior only actually
produce 2 or 3 possible valid images, being able to say that any of those
images are acceptable is simpler and less error-prone.
3. Better image storage. Traditionally, images had to either be included
directly in the repository or uploaded to a Google Storage bucket and pulled in
using the image's hash. The former allowed users to easily see which images were
currently approved, but storing large sized or numerous binary files in git is
generally discouraged due to the way git's history works. The latter worked
around the git issues, but made it much more difficult to actually see what was
being used since the only thing the user had to go on was a hash. Gold moves the
images out of the repository, but provides a GUI interface for easily seeing
which images are currently approved for a particular test.

### How It Works

Gold consists of two main parts: the Gold instance/service and the `goldctl`
binary. A Gold instance in turn consists of two parts: a Google Storage bucket
that data is uploaded to and a server running on GCE that ingests the data and
provides a way to triage diffs. `goldctl` simply provides a standardized way
of interacting with Gold - uploading data to the correct place, retrieving
baselines/golden information, etc.

In general, the following order of events occurs when running a Gold-enabled
test:

1. The test produces an image and passes it to `goldctl`, along with some
information about the hardware and software configuration that the image was
produced on, the test name, etc.
2. `goldctl` checks whether the hash of the produced image is in the list of
approved hashes.
    1. If it is, `goldctl` exits with a non-failing return code and nothing else
    happens. At this point, the test is finished.
    2. If it is not, `goldctl` uploads the image and metadata to the storage
    bucket and exits with a failing return code.
3. The server sees the new data in the bucket and ingests it, showing a new
untriaged image in the GUI.
4. A user approves the new image in the GUI, and the server adds the image's
hash to the baselines. See the [Waterfall Bots](#Waterfall-Bots) and
[Trybots](#Trybots) sections for specifics on this.
5. The next time the test is run, the new image is in the baselines, and
assuming the test produces the same image again, the test passes.

While this is the general order of events, there are several differences between
waterfall/CI bots and trybots.

#### Waterfall Bots

Waterfall bots are the simpler of the two bot types. There is only a single
set of baselines to worry about, which is whatever baselines were approved for
a git revision. Additionally, any new images that are produced on waterfalls are
all lumped into the same group of "untriaged images on master", and any images
that are approved from here will immediately be added to the set of baselines
for master.

Since not all waterfall bots have a trybot counterpart that can be relied upon
to catch newly produced images before a CL is committed, it is likely that a
change that produces new goldens on the CQ will end up making some of the
waterfall bots red for a bit, particularly those on chromium.gpu.fyi. They will
remain red until the new images are triaged as positive or the tests stop
producing the untriaged images. So, it is best to keep an eye out for a few
hours after your CL is committed for any new images from the waterfall bots that
need triaging.

#### Trybots

Trybots are a little more complicated when it comes to retrieving and approving
images. First, the set of baselines that are provided when requested by a test
is the union of the master baselines for the current revision and any baselines
that are unique to the CL. For example, if an image with the hash `abcd` is in
the master baselines for `FooTest` and the CL being tested has also approved
an image with the hash `abef` for `FooTest`, then the provided baselines will
contain both `abcd` and `abef` for `FooTest`.

When an image associated with a CL is approved, the approval only applies to
that CL until the CL is merged. Once this happens, any baselines produced by the
CL are automatically merged into the master baselines for whatever git revision
the CL was merged as. In the above example, if the CL was merged as commit
`ffff`, then both `abcd` and `abef` would be approved images on master from
`ffff` onward.

## Triaging Less Common Failures

### Triaging Images Without A Specific Build

You can see all currently untriaged images that are currently being produced on
ToT on the [GPU Gold instance's main page][gpu gold instance] and currently
untriaged images for a CL by substituting the Gerrit CL number into
`https://chrome-gold.skia.org/search?issue=[CL Number]&unt=true&master=true`.

[gpu gold instance]: https://chrome-gold.skia.org

It's possible, particularly if a test is regularly producing multiple images,
for an image to be untriaged but not show up on the front page of the Gold
instance (for details, see [this crbug comment][untriaged non tot comment]). To
see all such images, visit [this link][untriaged non tot].

[untriaged non tot comment]: https://bugs.chromium.org/p/skia/issues/detail?id=9189#c4
[untriaged non tot]: https://chrome-gold.skia.org/search?fdiffmax=-1&fref=false&frgbamax=255&frgbamin=0&head=false&include=false&limit=50&master=false&match=name&metric=combined&neg=false&offset=0&pos=false&query=source_type%3Dchrome-gpu&sort=desc&unt=true

### Finding A Failed Build

If for some reason you know that a test run produced a bad image, but do not
have a direct link to the failed build (e.g. you found a bad image using the
untriaged non-ToT link from above), you may want to find the failed Swarming
task to help debug the issue. Gold currently provides a list of CLs that were
under test when a particular image was produced, but does not provide a link to
the build that produced it, so the following workaround can be used.

Assuming the failure is relatively recent (within the past month or so), you
can use the test history view to help find the failed run. To do so, search for
the test name at `https://ci.chromium.org/ui/search?t=TESTS` and look through
the history for the failed build (represented in red). Click on the group of
builds and follow the link for the failing build, from which you can get to the
Swarming task like normal by scrolling to the failed step and clicking on the
link for the failed shard number.

### Triaging A Specific Image

If for some reason an image is not showing up in Gold but you know the hash, you
can manually navigate to the page for it by filling in the correct information
to `https://chrome-gold.skia.org/detail?test=[test_name]&digest=[hash]`.
From there, you should be able to triage it as normal.

If this happens, please also file a bug in [Skia's bug tracker][skia crbug] so
that the root cause can be investigated and fixed. It's likely that you will
be unable to directly edit the owner, CC list, etc. directly, in which case
ping kjlubick@ with a link to the filed bug to help speed up triaging. Include
as much detail as possible, such as a links to the failed swarming task and
the triage link for the problematic image.

[skia crbug]: https://bugs.chromium.org/p/skia

## Inexact Matching

By default, Gold uses exact matching with support for multiple baselines per
test. This works well for most of the GPU tests, but there are a handful of
tests such as `Pixel_CSS3DBlueBox` that are prone to noise which causes them to
need additional triaging at times.

For cases like this, using inexact matching can help, as it allows a comparison
to pass if there are only minor differences between the produced image and a
known-good image. Images that pass in this way will be automatically approved
in Gold, so there is still a record of exactly what was produced.

To enable this functionality, simply add a `matching_algorithm` field to the
`PixelTestPage` definition for the test (see other uses of this in the file for
concrete examples).

In order to determine which values to use, you can use the script located at
`//content/test/gpu/gold_inexact_matching/determine_gold_inexact_parameters.py`.

More complete documentation can be found in the `--help` output of the script,
but in general:
* Use the `binary_search` optimization algorithm if you only want to vary
    a single parameter, e.g. you only want to use a Sobel filter.
* Use the `local_minima` optimization algorithm if you want to vary multiple
    parameters, such as using fuzzy diffing + a Sobel filter together.
* The default boundaries and weights generally work and give good results, but
    you may need to tune them to better suit your particular test, e.g.
    increasing the maximum number of differing pixels if your image is large.

## Working On Gold

### Modifying Gold And goldctl

Although uncommon, changes to the Gold service and `goldctl` binary may be
needed. To do so, simply get a checkout of the
[Skia infrastructure repo][skia infra repo] and go through the same steps as
a Chromium CL (`git cl upload`, etc.).

[skia infra repo]: https://skia.googlesource.com/buildbot/

The Gold service code is located in the `//golden/` directory, while `goldctl`
is  located in `//gold-client/`. Once your change is merged, you will have to
either contact kjlubick@google.com to roll the service version or follow the
steps in [Rolling goldctl](#Rolling-goldctl) to roll the `goldctl` version used
by Chromium.

### Rolling goldctl

`goldctl` is available as a CIPD package and is DEPSed in as part of `gclient
sync` To update the binary used in Chromium, perform the following steps:

1. (One-time only) get an [infra checkout][infra repo]
2. Run `infra $ ./go/env.py` and run each of the commands it outputs to change
your GOPATH and other environment variables for your terminal
3. Update the Skia revision in [`deps.yaml`][deps yaml] to match the revision
of your `goldctl` CL (or some revision after it)
4. Run `infra $ ./go/deps.py update` and copy the list of repos it updated
(include this in your CL description)
5. Upload the changelist ([sample CL][sample roll cl])
6. Once the CL is merged, wait until the git revision of your merged CL shows
up in the tags of one of the instances for the [CIPD package][goldctl package]
7. Update the [revision in DEPS][goldctl deps entry] to be the merged CL's
revision

[infra repo]: https://chromium.googlesource.com/infra/infra/
[deps yaml]: https://chromium.googlesource.com/infra/infra/+/91333d832a4d871b4219580dfb874b49a97e6da4/go/deps.yaml#432
[sample roll cl]: https://chromium-review.googlesource.com/c/infra/infra/+/1493426
[goldctl package]: https://chrome-infra-packages.appspot.com/p/skia/tools/goldctl/linux-amd64/+/
[goldctl deps entry]: https://chromium.googlesource.com/chromium/src/+/6b7213a45382f01ac0a2efec1015545bd051da89/DEPS#1304

If you want to make sure that `goldctl` builds after the update before
committing (e.g. to ensure that no extra third party dependencies were added),
run the following after the `./go/deps.py update` step:

1. `infra $ ./go/deps.py install`
2. `infra $ go install go.skia.org/infra/gold-client/cmd/goldctl`
3. `infra $ which goldctl` which should point to a binary in `infra/go/bin/`
4. `infra $ goldctl` to make sure it actually runs


text:
psychic-dangerzone
==================

Just a playground for some offline testing... service workers, appcache

redpajama_set_name: RedPajamaGithub


text:
using System;
using System.Threading;

using NUnit.Framework;

namespace NUnit.TestData
{
    [TestFixture]
    public class MaxTimeFixture
    {
        [Test, MaxTime(1)]
        public void MaxTimeExceeded()
        {
#if SILVERLIGHT
            // Silverlight does not have the high resolution StopWatch, so
            // we need to delay longer than their minimum clock resolution
            Thread.Sleep(1000);
#else
            Thread.Sleep(20);
#endif
        }
    }

    [TestFixture]
    public class MaxTimeFixtureWithTestCase
    {
        [TestCase(5), MaxTime(1)]
        public void MaxTimeExceeded(int x)
        {
#if SILVERLIGHT
            // Silverlight does not have the high resolution StopWatch, so
            // we need to delay longer than their minimum clock resolution
            Thread.Sleep(1000);
#else
            Thread.Sleep(20);
#endif
        }
    }

    [TestFixture]
    public class MaxTimeFixtureWithFailure
    {
        [Test, MaxTime(1)]
        public void MaxTimeExceeded()
        {
            Thread.Sleep(20);
            Assert.Fail("Intentional Failure");
        }
    }

    [TestFixture]
    public class MaxTimeFixtureWithError
    {
        [Test, MaxTime(1)]
        public void MaxTimeExceeded()
        {
            Thread.Sleep(20);
            throw new Exception("Exception message");
        }
    }
}
#endif


text:
import unittest

from click.testing import CliRunner

from stickshift.migration_repository import MigrationRepository
from stickshift.database_manager import DatabaseManager

from stickshift.cli import cli
from stickshift.cli_strings import CLIStrings

class CLITests(unittest.TestCase):

    def setUp(self):
        self.migration_repository = MigrationRepository()
        self.migration_repository.clear()
        self.runner = CliRunner()

    def tearDown(self):
        self.migration_repository.clear()

    def test_cli(self):
        result = self.runner.invoke(cli, ["--help"])
        self.assertEqual(result.exit_code, 0)

    def test_cli_setup(self):
        result = self.runner.invoke(cli, ["setup"])
        self.assertEqual(result.exit_code, 0)
        self.assertTrue(CLIStrings.DB_MIGRATION_REPOSITORY_CREATED == result.output.rstrip(), "output incorrect")

    def test_cli_setup_after_already_setup(self):
        result = self.runner.invoke(cli, ["setup"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), CLIStrings.DB_MIGRATION_REPOSITORY_CREATED, "output incorrect")
        result = self.runner.invoke(cli, ["setup"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), CLIStrings.DB_MIGRATION_REPOSITORY_ALREADY_CREATED, "output incorrect")

    def test_cli_clear_after_setup(self):
        result = self.runner.invoke(cli, ["setup"])
        self.assertEqual(result.exit_code, 0)
        result = self.runner.invoke(cli, ["clear"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), CLIStrings.DB_MIGRATION_REPOSITORY_CLEARED, "output incorrect")

    def test_cli_clear_after_already_cleared(self):
        result = self.runner.invoke(cli, ["setup"])
        self.assertEqual(result.exit_code, 0)
        result = self.runner.invoke(cli, ["clear"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), CLIStrings.DB_MIGRATION_REPOSITORY_CLEARED, "output incorrect")

    def test_cli_database_command_when_not_setup(self):
        result = self.runner.invoke(cli, ["db", "provision", "DATABASE"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), CLIStrings.DB_MIGRATION_REPOSITORY_MUST_BE_SETUP)

    def test_cli_clear_when_not_setup(self):
        result = self.runner.invoke(cli, ["clear"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), CLIStrings.DB_MIGRATION_REPOSITORY_DOESNT_EXIST_AT_DIRECTORY)

    def test_cli_new_when_not_setup(self):
        result = self.runner.invoke(cli, ["new", "table", "test"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), CLIStrings.DB_MIGRATION_REPOSITORY_MUST_BE_SETUP)

class CLIDatabaseTests(unittest.TestCase):

    def setUp(self):
        self.migration_repository = MigrationRepository()
        self.migration_repository.clear()
        self.migration_repository.create_repository()
        self.database_manager = DatabaseManager(migration_repository=self.migration_repository,
                                                environment="DATABASE")
        self.runner = CliRunner()

    def tearDown(self):
        if self.database_manager.is_database_provisioned():
            self.database_manager.reset()
            self.database_manager.deprovision_database()
        self.migration_repository.clear()

    def test_cli_provision_database(self):
        result = self.runner.invoke(cli, ["db", "provision", "DATABASE"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), CLIStrings.DB_DATABASE_PROVISIONED_SUCCESSFULLY)
        self.assertTrue(self.database_manager.is_database_provisioned())

    def test_cli_deprovision_database(self):
        result = self.runner.invoke(cli, ["db", "provision", "DATABASE"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), CLIStrings.DB_DATABASE_PROVISIONED_SUCCESSFULLY)
        self.assertTrue(self.database_manager.is_database_provisioned())

        result = self.runner.invoke(cli, ["db", "deprovision", "DATABASE"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), CLIStrings.DB_DATABASE_DEPROVISIONED_SUCCESSFULLY)
        self.assertFalse(self.database_manager.is_database_provisioned())

    def test_cli_provision_when_already_provisioned(self):
        result = self.runner.invoke(cli, ["db", "provision", "DATABASE"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), CLIStrings.DB_DATABASE_PROVISIONED_SUCCESSFULLY)
        self.assertTrue(self.database_manager.is_database_provisioned())

        result = self.runner.invoke(cli, ["db", "provision", "DATABASE"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), CLIStrings.DB_DATABASE_IS_ALREADY_PROVISIONED)
        self.assertTrue(self.database_manager.is_database_provisioned())

    def test_cli_deprovision_when_not_provisioned(self):
        result = self.runner.invoke(cli, ["db", "deprovision", "DATABASE"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), CLIStrings.DB_DATABASE_IS_NOT_PROVISIONED)
        self.assertFalse(self.database_manager.is_database_provisioned())

    def test_cli_version_non_migrated(self):
        result = self.runner.invoke(cli, ["db", "provision", "DATABASE"])
        self.assertEqual(result.exit_code, 0)

        result = self.runner.invoke(cli, ["db", "version", "DATABASE"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), CLIStrings.DB_DATABASE_NOT_MIGRATED_YET)

    def test_cli_version_migrated(self):
        result = self.runner.invoke(cli, ["db", "provision", "DATABASE"])
        self.assertEqual(result.exit_code, 0)

        self.runner.invoke(cli, ["new", "table", "test"])
        self.runner.invoke(cli, ["db", "migrate", "DATABASE"])

        result = self.runner.invoke(cli, ["db", "version", "DATABASE"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), "{0}: {1}".format(CLIStrings.DB_DATABASE_VERSION, 0))

    def test_cli_list_tables(self):
        result = self.runner.invoke(cli, ["db", "provision", "DATABASE"])
        self.assertEqual(result.exit_code, 0)

        result = self.runner.invoke(cli, ["db", "tables", "DATABASE"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), "\nTABLES\n--------\nversion_migration\n--------")

    def test_cli_list_procedures(self):
        result = self.runner.invoke(cli, ["db", "procedures", "DATABASE"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(result.output.rstrip(), "\nPROCEDURES\n--------\n--------")

    def test_cli_upgrade(self):
        result = self.runner.invoke(cli, ["db", "provision", "DATABASE"])
        self.assertEqual(result.exit_code, 0)

        self.runner.invoke(cli, ["new", "table", "test"])
        self.runner.invoke(cli, ["db", "upgrade", "DATABASE"])

        self.assertEqual(result.exit_code, 0)
        self.assertEqual(self.database_manager.current_database_migration_version(), 0)

    def test_cli_downgrade(self):
        result = self.runner.invoke(cli, ["db", "provision", "DATABASE"])
        self.assertEqual(result.exit_code, 0)

        self.runner.invoke(cli, ["new", "table", "test"])
        self.runner.invoke(cli, ["db", "upgrade", "DATABASE"])

        self.assertEqual(result.exit_code, 0)
        self.assertEqual(self.database_manager.current_database_migration_version(), 0)

        result = self.runner.invoke(cli, ["db", "downgrade", "DATABASE"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(self.database_manager.current_database_migration_version(), None)

    def test_cli_migrate(self):
        result = self.runner.invoke(cli, ["db", "provision", "DATABASE"])
        self.assertEqual(result.exit_code, 0)

        self.runner.invoke(cli, ["new", "table", "test"])
        self.runner.invoke(cli, ["db", "upgrade", "DATABASE"])

        self.assertEqual(result.exit_code, 0)
        self.assertEqual(self.database_manager.current_database_migration_version(), 0)

    def test_cli_reset(self):
        result = self.runner.invoke(cli, ["db", "provision", "DATABASE"])
        self.assertEqual(result.exit_code, 0)

        self.runner.invoke(cli, ["new", "table", "test"])
        self.runner.invoke(cli, ["db", "migrate", "DATABASE"])

        self.assertEqual(result.exit_code, 0)
        self.assertEqual(self.database_manager.current_database_migration_version(), 0)

        result = self.runner.invoke(cli, ["db", "reset", "DATABASE"])
        self.assertEqual(result.exit_code, 0)
        self.assertEqual(self.database_manager.current_database_migration_version(), None)


text:
//
// Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

/**
* @file      torus.cpp
* @brief     torus triangle mesh
*/

#include "gu_make_ib.hpp"
#include <stdexcept>

namespace
{
    float const pi = 3.1415926536f;
    float const pi_x_2 = 2.f * pi;
    float const pi_div_2 = pi / 2.f;

    void add_circle_vb(gu::vertex_buffer& vb, float major, float minor, size_t circle_id, size_t num_circle, size_t num_pt)
    {
        assert(num_pt > 1);

        gu::vertex v{};
        v.uv.x = static_cast<float>(circle_id) / static_cast<float>(num_circle - 1);

        float phi = v.uv.x * pi_x_2;
        float cphi = std::cos(phi);
        float sphi = std::sin(phi);

        for (std::size_t i = 0; i < num_pt; ++i)
        {
            v.uv.y = static_cast<float>(i) / static_cast<float>(num_pt - 1);

            float theta = v.uv.y * pi_x_2;
            float ctheta = std::cos(theta);
            float stheta = std::sin(theta);

            v.normal.x = ctheta * cphi;
            v.normal.y = ctheta * sphi;
            v.normal.z = -stheta;

            v.tangent.x = -stheta * cphi;
            v.tangent.y = -stheta * sphi;
            v.tangent.z = ctheta;

            v.position = tml::vec3{ major * cphi, major * sphi, 0 } + minor * v.normal;

            vb.push_back(v);
        }
    }

    gu::vertex_buffer make_torus_vb(float major, float minor, std::size_t num_circle, std::size_t num_pt)
    {
        assert(num_circle > 1);
        gu::vertex_buffer vb(num_circle * num_pt);
        vb.resize(0);

        for (std::size_t i = 0; i < num_circle; ++i)
        {
            add_circle_vb(vb, major, minor, i, num_circle, num_pt);
        }

        assert(vb.size() == num_circle * num_pt);

        return vb;
    }

} // namespace

namespace gu
{
    vertex_buffer_object make_torus(float major_radius, float minor_radius, std::size_t num_circle, std::size_t num_pt)
    {
        assert(num_circle > 1 && num_pt > 1);
        if (num_circle < 2 || num_pt < 2)
        {
            throw std::runtime_error{ "wrong make_torus parameters" };
        }

        return
        {
            make_torus_vb(major_radius, minor_radius, num_circle, num_pt),
            make_ib(num_circle, num_pt)
        };
    }

} // namespace


text:
<?php

namespace Baleen\Cli\CommandBus\Config;

use Symfony\Component\Console\Command\Command;

/**
 * Message class for the config:init command.
 *
 * @author Gabriel Somoza <gabriel@strategery.io>
 */
class InitMessage extends AbstractConfigMessage
{
    /**
     * @inheritdoc
     */
    public static function configure(Command $command)
    {
        $command->setName('config:init');
        $command->setAliases(['init']);
        $command->setDescription('Initialises Baleen by creating a config file in the current directory.');
    }
}


text:
package ru.skafcats.hackathon;

import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;

/**
 * Created by Nikita Kulikov on 29.03.17.
 * <p>
 * Возможно полное или частичное копирование
 */

public class RegistryActivity extends Activity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_registry);
    }
}


text:
namespace stk {
namespace diag {

WriterParser::WriterParser()
  : OptionMaskParser()
{
  mask("coverage", 0, "Collect and display traceable function usage coverage");
  mask("members", LOG_MEMBERS, "Display data structure members messages");
  mask("trace", LOG_TRACE, "Display execution trace");
  mask("trace-stats", LOG_TRACE_STATS, "Display execution time and memory usage during trace");
  mask("trace-down", LOG_TRACE_SUB_CALLS, "Display subsequent calls after tracing is enabled");
}

OptionMaskParser::Mask
WriterParser::parse(
  const char *          mask_string) const
{
  m_optionMask = LOG_MEMBERS;
  return OptionMaskParser::parse(mask_string);
}

void
WriterParser::parseArg(
  const std::string &  name,
  const std::string &  arg) const
{
  if (name == "trace") {
    m_optionMask |= LOG_TRACE;
    if (!arg.empty()) {
      std::string::const_iterator it0 = arg.begin();
      std::string::const_iterator it1;
      std::string::const_iterator it2;
      do {
        // Trim preceeding spaces
        while (it0 != arg.end() && *it0 == ' ')
          it0++;

        if (it0 == arg.end())
          break;

        int paren_count = 0;
        for (it1 = it0; it1 != arg.end(); ++it1) {
          if (*it1 == '(')
            ++paren_count;
          else if (*it1 == ')')
            --paren_count;
          else if (*it1 == ',' && paren_count == 0)
            break;
        }

        // Trim trailing spaces
        it2 = it1;
        while (it2 != it0 && *(it2 - 1) == ' ')
          --it2;

        std::string function(it0, it2);

        Trace::addTraceFunction(function);

        it0 = it1 + 1;
      } while (it1 != arg.end());
    }
    else
      m_optionMask |= LOG_TRACE_SUB_CALLS;
  }

  else {
    OptionMaskNameMap::const_iterator mask_entry = m_optionMaskNameMap.find(name.c_str());

    if (mask_entry != m_optionMaskNameMap.end())
      m_optionMask |= (*mask_entry).second.m_mask;
    else {
      Mask  mask_hex = 0;
      std::istringstream mask_hex_stream(name.c_str());
      if (mask_hex_stream >> std::resetiosflags(std::ios::basefield) >> mask_hex)
        m_optionMask |= mask_hex;
      else
        m_status = false;
    }
  }
}

OptionMaskParser::Mask
OptionMaskParser::parse(
  const char *          mask) const
{
  if (mask) {
    const std::string mask_string(mask);

    m_status = true;

    std::string::const_iterator it0 = mask_string.begin();
    std::string::const_iterator it1;
    std::string::const_iterator it2;
    std::string::const_iterator it3;
    do {
      // Trim preceeding spaces
      while (it0 != mask_string.end() && *it0 == ' ')
        it0++;

      if (it0 == mask_string.end())
        break;

      for (it1 = it0; it1 != mask_string.end(); ++it1) {
        if (*it1 == '(' || *it1 == ':' || *it1 == ',')
          break;
      }

      // Trim trailing spaces
      it2 = it1;
      while (it2 != it0 && *(it2 - 1) == ' ')
        --it2;

      std::string name(it0, it2);

      // Get argument list
      if (*it1 == '(') {
        it2 = it1 + 1;

        // Trim preceeding spaces
        while (it2 != mask_string.end() && *it2 == ' ')
          ++it2;

        int paren_count = 0;

        for (; it1 != mask_string.end(); ++it1) {
          if (*it1 == '(')
            ++paren_count;
          else if (*it1 == ')') {
            --paren_count;
            if (paren_count == 0)
              break;
          }
        }
        it3 = it1;

        // Trim trailing spaces
        while (it3 != it2 && *(it3 - 1) == ' ')
          --it3;

        // Find next argument start
        for (; it1 != mask_string.end(); ++it1)
          if (*it1 == ':' || *it1 == ',')
            break;
      }
      else
        it2 = it3 = it1;

      const std::string arg(it2, it3);

      parseArg(name, arg);

      it0 = it1 + 1;
    } while (it1 != mask_string.end());
  }

  return m_optionMask;
}

void
OptionMaskParser::parseArg(
  const std::string &  name,
  const std::string &  arg) const
{
  OptionMaskNameMap::const_iterator mask_entry = m_optionMaskNameMap.find(name);

  if (mask_entry != m_optionMaskNameMap.end()) m_optionMask |= (*mask_entry).second.m_mask;
  else {
    Mask  mask_hex = 0;
    std::istringstream mask_hex_stream(name.c_str());
    if (mask_hex_stream >> std::resetiosflags(std::ios::basefield) >> mask_hex)
      m_optionMask |= mask_hex;
    else
      m_status = false;
  }
}

std::ostream &
OptionMaskParser::describe(
  std::ostream &    os) const
{
  os << "Specify a comma separated list of:" << std::endl;
  for (OptionMaskNameMap::const_iterator it = m_optionMaskNameMap.begin(); it != m_optionMaskNameMap.end(); ++it)
    (*it).second.describe(os);

  return os;
}

std::ostream &
OptionMaskName::describe(
  std::ostream &  os) const
{
  return os << "  " << std::left << std::setw(20) << m_name << "\t" << m_description << std::endl;
}

} // namespace diag
} // namespace stk


text:
module Domgen
  module Imit
    class DefaultValues < Domgen.ParentedElement(:entity)
      def initialize(entity, defaults, options = {}, &block)
        raise "Attempted to define test_default on abstract entity #{entity.qualified_name}" if entity.abstract?
        raise "Attempted to define test_default on #{entity.qualified_name} with no values" if defaults.empty?
        defaults.keys.each do |key|
          raise "Attempted to define test_default on #{entity.qualified_name} with key '#{key}' that is not an attribute value" unless entity.attribute_by_name?(key)
          a = entity.attribute_by_name(key)
          raise "Attempted to define test_default on #{entity.qualified_name} for attribute '#{key}' when attribute has no imit facet defined. Defaults = #{defaults.inspect}" unless a.imit?
        end
        values = {}
        defaults.each_pair do |k, v|
          values[k.to_s] = v
        end
        @values = values

        super(entity, options, &block)
      end

      def has_attribute?(name)
        @values.keys.include?(name.to_s)
      end

      def value_for(name)
        @values[name.to_s]
      end

      def values
        @values.dup
      end
    end

    class ReplicationGraph < Domgen.ParentedElement(:application)
      def initialize(application, name, options, &block)
        @name = name
        @type_roots = []
        @required_type_graphs = []
        @dependent_type_graphs = []
        @instance_root = nil
        @outward_graph_links = {}
        @inward_graph_links = {}
        @routing_keys = {}
        @visibility = :universal
        application.send :register_graph, name, self
        super(application, options, &block)
      end

      include Domgen::Java::BaseJavaGenerator
      include Domgen::Java::JavaClientServerApplication

      java_artifact :react4j_subscription_component, :component, :client, :imit, '#{name}GraphSubscription'

      Domgen.target_manager.target(:graph, :repository, :facet_key => :imit, :access_method => :graphs)

      attr_reader :application

      attr_reader :name

      def qualified_name
        "#{application.repository.qualified_name}.Graphs.#{name}"
      end

      def to_s
        "ReplicationGraph[#{qualified_name}]"
      end

      def cacheable?
        !!@cacheable
      end

      def cacheable=(cacheable)
        @cacheable = cacheable
      end

      def bulk_load?
        !!@bulk_load
      end

      def bulk_load=(bulk_load)
        @bulk_load = bulk_load
      end

      def visibility=(visibility)
        valid_values = [:external, :internal, :universal]
        Domgen.error("Invalid visibility set on #{qualified_name}. Value: #{visibility}. Valid_values: #{valid_values}") unless valid_values.include?(visibility)
        @visibility = visibility
      end

      def visibility
        @visibility
      end

      def external_visibility?
        self.visibility == :external || self.universal_visibility?
      end

      def internal_visibility?
        self.visibility == :internal || self.universal_visibility?
      end

      # Default visibility is both internal and externally visible
      # So a user can both subscribe to graph explicitly and a graph can graph_link to this graph
      def universal_visibility?
        self.visibility == :universal
      end

      def external_data_load?
        filtered? || (@external_data_load.nil? ? false : !!@external_data_load)
      end

      def external_data_load=(external_data_load)
        @external_data_load = external_data_load
      end

      def external_cache_management?
        Domgen.error("external_cache_management? invoked on #{qualified_name} when not cacheable") unless cacheable?
        @external_cache_management.nil? ? false : !!@external_cache_management
      end

      def external_cache_management=(external_cache_management)
        @external_cache_management = external_cache_management
      end

      def instance_root?
        !@instance_root.nil?
      end

      def type_roots
        Domgen.error("type_roots invoked for graph #{name} when instance based") if instance_root?
        @type_roots
      end

      def type_roots=(type_roots)
        Domgen.error("Attempted to assign type_roots #{type_roots.inspect} for graph #{name} when instance based on #{@instance_root.inspect}") if instance_root?
        @type_roots = type_roots
      end

      def instance_root
        Domgen.error("instance_root invoked for graph #{name} when not instance based") if 0 != @type_roots.size
        @instance_root
      end

      def instance_root=(instance_root)
        Domgen.error("Attempted to assign instance_root to #{instance_root.inspect} for graph #{name} when not instance based (type_roots=#{@type_roots.inspect})") if 0 != @type_roots.size
        @instance_root = instance_root
      end

      def outward_graph_links
        @outward_graph_links.values
      end

      def inward_graph_links
        Domgen.error("inward_graph_links invoked for graph #{name} when not instance based") if 0 != @type_roots.size
        @inward_graph_links.values
      end

      def routing_keys
        Domgen.error("routing_keys invoked for graph #{name} when not filtered") if unfiltered?
        @routing_keys.values
      end

      # Return the list of entities reachable in instance graph
      def reachable_entities
        Domgen.error("reachable_entities invoked for graph #{name} when not instance based") if 0 != @type_roots.size
        @reachable_entities ||= []
      end

      def included_entities
        instance_root? ? reachable_entities : type_roots
      end

      def filter(filter_type, options = {}, &block)
        Domgen.error("Attempting to redefine filter on graph #{self.name}") if @filter
        @filter ||= FilterParameter.new(self, filter_type, options, &block)
      end

      def filter_parameter?
        !@filter.nil?
      end

      def filter_parameter
        @filter
      end

      def filtered?
        (@filtered.nil? ? false : !!@filtered) || filter_parameter?
      end

      attr_writer :filtered

      def unfiltered?
        !filtered?
      end

      def dependent_type_graphs
        @dependent_type_graphs.dup
      end

      def required_type_graphs
        @required_type_graphs.dup
      end

      def require_type_graphs=(require_type_graphs)
        require_type_graphs.each do |graph_key|
          require_type_graph(graph_key)
        end
      end

      def require_type_graph(graph_key)
        graph = application.repository.imit.graph_by_name(graph_key)
        Domgen.error("Graph '#{self.name}' requires type graph #{graph_key} but required graph is not a type graph.") if graph.instance_root?
        Domgen.error("Graph '#{self.name}' requires self which is invalid.") if self.name.to_s == graph_key.to_s
        Domgen.error("Graph '#{self.name}' requires type graph #{graph_key} multiple times.") if @required_type_graphs.include?(graph)
        @required_type_graphs << graph
        graph.send(:add_dependent_type_graph, self)
      end

      def post_verify
        if cacheable? && (filter_parameter || instance_root?)
          Domgen.error("Graph #{self.name} can not be marked as cacheable as cacheable graphs are not supported for instance based or filterable graphs")
        end
        if self.instance_root?
          instance_root = self.application.repository.entity_by_name(self.instance_root)
          unless instance_root.primary_key.integer?
            Domgen.error("Graph #{self.name} has an instance root #{self.instance_root} that has a primary key that is not an integer")
          end
        end
        self.outward_graph_links.select { |graph_link| graph_link.auto? }.each do |graph_link|
          target_graph = application.repository.imit.graph_by_name(graph_link.target_graph)
          if target_graph.filter_parameter? && self.unfiltered?
            Domgen.error("Graph '#{self.name}' is an unfiltered graph but has an outward link from '#{graph_link.imit_attribute.attribute.qualified_name}' to a filtered graph '#{target_graph.name}' that requires a filter parameter. This is not supported.")
          elsif target_graph.filter_parameter? && self.filtered? && !target_graph.filter_parameter.equiv?(self.filter_parameter)
            Domgen.error("Graph '#{self.name}' has an outward link from '#{graph_link.imit_attribute.attribute.qualified_name}' to a filtered graph '#{target_graph.name}' but has a different filter parameter. This is not supported.")
          end
        end

        if self.internal_visibility? && self.instance_root? && self.inward_graph_links.empty?
          Domgen.error("Graph '#{self.name}' is marked with internal visibility but has no inward graph links.")
        end

        if self.internal_visibility? && !self.instance_root? && self.dependent_type_graphs.empty?
          Domgen.error("Graph '#{self.name}' is a type graph marked with internal visibility but has no dependent type graphs.")
        end

        rtgs = self.required_type_graphs

        entities = self.included_entities

        entities.each do |entity_name|
          entity = application.repository.entity_by_name(entity_name)
          entity.attributes.select { |a| a.reference? && a.imit? }.each do |a|
            referenced_entity = a.referenced_entity

            agls = a.imit.auto_graph_links

            next if agls.any? { |graph_link| graph_link.source_graph.to_s == self.name.to_s }

            # Unclear on how to handle this next scenario. Assume a subtype is visible?
            next if referenced_entity.abstract?

            # If linked entity is part of current graph then all is ok.
            next if entities.any? { |e| e == referenced_entity.qualified_name }

            # If entity is part of required type graphs then all is ok
            next if rtgs.any? { |g| g.type_roots.include?(referenced_entity.qualified_name) }

            next if self.instance_root? &&
              !self.inward_graph_links.empty? &&
              self.inward_graph_links.all? do |graph_link|
                application.repository.imit.graph_by_name(graph_link.source_graph).included_entities.any? { |e| e == referenced_entity.qualified_name }
              end

            Domgen.error("Graph '#{self.name}' has a link from '#{a.qualified_name}' to entity '#{referenced_entity.qualified_name}' that is not a instance level graph-link and is not part of any of the dependent type graphs: #{rtgs.collect { |e| e.name }.inspect} and not in current graph [#{entities.join(', ')}].")
          end
        end
      end

      protected

      def add_dependent_type_graph(graph)
        @dependent_type_graphs << graph
      end

      def register_routing_key(routing_key)
        key = routing_key.name.to_s
        Domgen.error("Attempted to register duplicate routing key link on attribute '#{routing_key.imit_attribute.attribute.qualified_name}' on graph '#{self.name}'") if @routing_keys[key]
        @routing_keys[key] = routing_key
      end

      def register_outward_graph_link(graph_link)
        to_graph = graph_link.target_graph
        key = "#{to_graph}-#{graph_link.imit_attribute.attribute.qualified_name.to_s}"
        Domgen.error("Attempted to register duplicate outward graph link on attribute '#{graph_link.imit_attribute.attribute.qualified_name}' on graph '#{self.name}'") if @outward_graph_links[key]
        @outward_graph_links[key] = graph_link
      end

      def register_inward_graph_link(graph_link)
        from_graph = graph_link.source_graph
        key = "#{from_graph}-#{graph_link.imit_attribute.attribute.qualified_name.to_s}"
        Domgen.error("Attempted to register duplicate inward graph link on attribute '#{graph_link.imit_attribute.attribute.qualified_name}' on graph '#{self.name}' from graph '#{from_graph}'") if @inward_graph_links[key]
        @inward_graph_links[key] = graph_link
      end
    end

    class GraphLink < Domgen.ParentedElement(:imit_attribute)
      def initialize(imit_attribute, name, source_graph, target_graph, options, &block)
        repository = imit_attribute.attribute.entity.data_module.repository
        unless repository.imit.graph_by_name?(source_graph)
          Domgen.error("Source graph '#{source_graph}' specified for link on #{imit_attribute.attribute.name} does not exist")
        end
        unless repository.imit.graph_by_name?(target_graph)
          Domgen.error("Target graph '#{target_graph}' specified for link on #{imit_attribute.attribute.name} does not exist")
        end
        unless imit_attribute.attribute.reference? || imit_attribute.attribute.primary_key?
          Domgen.error("Attempted to define a graph link on non-reference, non-primary key attribute '#{imit_attribute.attribute.qualified_name}'")
        end
        @name = name
        @source_graph = source_graph
        @target_graph = target_graph
        @auto = !imit_attribute.attribute.primary_key?
        super(imit_attribute, options, &block)
        repository.imit.graph_by_name(source_graph).send(:register_outward_graph_link, self)
        repository.imit.graph_by_name(target_graph).send(:register_inward_graph_link, self)
        self.exclude_target = false unless repository.imit.graph_by_name(target_graph).instance_root?
        self.imit_attribute.attribute.inverse.imit.exclude_edges << target_graph if self.exclude_target?
      end

      attr_reader :name
      attr_reader :source_graph
      attr_reader :target_graph

      attr_accessor :path

      attr_writer :auto

      def auto?
        !!@auto
      end

      # Set this to true if this link may link to a different instance of a graph already linked to
      # the current graph. Current Event/1 instance graph link may graph_link to Event/2. Another example is
      # Event/1 is linked to from OrgUnit/1 and wants to graph_link to OrgUnit/2. Setting this parameter forces
      # collection of routing data and allows a later stage to filter already present links
      attr_writer :always_follow

      def always_follow?
        @always_follow.nil? ? false : !!@always_follow
      end

      attr_writer :exclude_target

      # Should we exclude the target entity from source graph? Typically done for automatically
      # traversing graphs but sometimes you may wish to override this.
      def exclude_target?
        @exclude_target.nil? ? self.auto? : !!@exclude_target
      end

      def to_s
        "GraphLink[#{source_graph} => #{target_graph}](auto=#{auto?}, exclude_target=#{exclude_target?}, path=#{path.inspect}, name=#{name})"
      end

      def post_verify
        entity = self.imit_attribute.attribute.primary_key? ? self.imit_attribute.attribute.entity : self.imit_attribute.attribute.referenced_entity

        # Need to make sure that the path is valid
        if self.path
          prefix = "Graph link from '#{self.source_graph}' to '#{self.target_graph}' via '#{self.imit_attribute.attribute.name}' with path element"
          self.path.to_s.split.each_with_index do |attribute_name_path_element, i|
            other = entity.attribute_by_name(attribute_name_path_element)
            Domgen.error("#{prefix} #{attribute_name_path_element} is nullable") if other.nullable? && i != 0
            Domgen.error("#{prefix} #{attribute_name_path_element} is not immutable") unless other.immutable?
            Domgen.error("#{prefix} #{attribute_name_path_element} is not a reference") unless other.reference?
            entity = other.referenced_entity
          end
        end

        repository = imit_attribute.attribute.entity.data_module.repository
        source_graph = repository.imit.graph_by_name(self.source_graph)
        target_graph = repository.imit.graph_by_name(self.target_graph)

        # Need to make sure both graphs are instance graphs
        prefix = "Graph link from '#{self.source_graph}' to '#{self.target_graph}' via '#{self.imit_attribute.attribute.name}'"
        Domgen.error("#{prefix} must have an instance graph on the LHS if target graph has filter as we assume filter is propagated") unless source_graph.instance_root? || target_graph.unfiltered?
        Domgen.error("#{prefix} must have an instance graph on the RHS") unless target_graph.instance_root?

        # Need to make sure that the other side is the root of the graph
        unless target_graph.instance_root != entity.name
          Domgen.error("Graph link from '#{self.source_graph}' to '#{self.target_graph}' via '#{self.imit_attribute.attribute.qualified_name}' links to entity that is not the root of the graph")
        end

        elements = (source_graph.instance_root? ? source_graph.reachable_entities.sort : source_graph.type_roots)
        unless elements.include?(self.imit_attribute.attribute.entity.qualified_name)
          Domgen.error("Graph link from '#{self.source_graph}' to '#{self.target_graph}' via '#{self.imit_attribute.attribute.qualified_name}' attempts to link to a graph when the source entity is not part of the source graph - #{elements.inspect}")
        end

        elements = (target_graph.instance_root? ? target_graph.reachable_entities.sort : target_graph.type_roots)
        unless elements.include?(entity.qualified_name)
          Domgen.error("Graph link from '#{self.source_graph}' to '#{self.target_graph}' via '#{self.imit_attribute.attribute.qualified_name}' attempts to link to a graph when the target entity is not part of the target graph - #{elements.inspect}")
        end
      end
    end

    class RoutingKey < Domgen.ParentedElement(:imit_attribute)
      def initialize(imit_attribute, name, graph, options, &block)
        repository = imit_attribute.attribute.entity.data_module.repository
        unless repository.imit.graph_by_name?(graph)
          Domgen.error("Graph '#{graph}' specified for routing key #{name} on #{imit_attribute.attribute.name} does not exist")
        end
        @name = name
        @graph = repository.imit.graph_by_name(graph)
        Domgen.error("Routing key '#{name}' on #{imit_attribute.attribute.name} is not immutable") unless imit_attribute.attribute.immutable?
        super(imit_attribute, options, &block)
        repository.imit.graph_by_name(graph).send :register_routing_key, self
      end

      # A unique name for routing key within the graph
      attr_reader :name

      # The graph that routing key is used by
      attr_reader :graph

      # The path is the chain of references along which routing key walks
      # Each link in chain must be a reference. Must be empty if initial
      # attribute is not a reference. A null in the path means nokey is
      # selected
      def path
        @path || []
      end

      def path=(path)
        Domgen.error("Path parameter '#{path.inspect}' specified for routing key #{name} on #{imit_attribute.attribute.name} is not an array") unless path.is_a?(Array)
        path.each do |path_key|
          self.multivalued = true if is_inverse_path_element?(path_key) || is_path_element_recursive?(path_key)
        end
        @path = path
      end

      def is_path_element_recursive?(path_element)
        path_element.to_s =~ /^\*.*/
      end

      def is_inverse_path_element?(path_element)
        path_element.to_s =~ /^<.*/
      end

      def get_attribute_name_from_path_element?(path_element)
        is_inverse_path_element?(path_element) || is_path_element_recursive?(path_element) ? path_element[1, path_element.length] : path_element
      end

      # The name of the attribute that is used in referenced entity. This
      # will raise an exception if the initial attribute is not a reference, otherwise
      # it must match a name in the target entity
      def attribute_name
        Domgen.error("attribute_name invoked for routing key #{name} on #{imit_attribute.attribute.name} when attribute is not a reference or inverse reference") unless reference? || inverse_start?
        return @attribute_name unless @attribute_name.nil?
        referenced_entity.primary_key.name
      end

      def attribute_name=(attribute_name)
        @attribute_name = attribute_name
      end

      def attribute_name?
        !@attribute_name.nil?
      end

      def reference?
        self.path.size > 0 || self.imit_attribute.attribute.reference?
      end

      def referenced_attribute
        reference? || inverse_start? ? self.referenced_entity.attribute_by_name(self.attribute_name) : imit_attribute.attribute
      end

      def referenced_entity
        Domgen.error("referenced_entity invoked on routing key #{name} on #{imit_attribute.attribute.name} when attribute is not a reference or inverse reference") unless reference? || inverse_start?
        a = imit_attribute.attribute
        e = self.imit_attribute.attribute.reference? ? self.imit_attribute.attribute.referenced_entity : a.entity
        path.each do |path_element|
          attr_name = get_attribute_name_from_path_element?(path_element)
          if is_inverse_path_element?(path_element)
            a = e.arez.referencing_client_side_attributes.select { |attr| attr.inverse.name.to_s == attr_name.to_s }[0]
            e = a.entity
          else
            a = e.attribute_by_name(attr_name)
            e = a.referenced_entity
          end
        end
        e
      end

      def inverse_start?
        self.imit_attribute.attribute.primary_key? && self.path.size > 0
      end

      def target_attribute
        ((!self.inverse_start? && self.reference?) || self.attribute_name?) ? self.referenced_entity.attribute_by_name(self.attribute_name) : self.imit_attribute.attribute
      end

      attr_writer :multivalued

      def multivalued?
        @multivalued.nil? ? false : !!@multivalued
      end

      def target_nullsafe?
        return true unless self.reference?
        return false if self.inverse_start?
        return self.imit_attribute.attribute.reference? if self.path.size == 0

        a = imit_attribute.attribute
        self.path.each do |path_element|
          return false if is_path_element_recursive?(path_element)
          return false if is_inverse_path_element?(path_element)
          a = a.referenced_entity.attribute_by_name(get_attribute_name_from_path_element?(path_element))
          return false if a.nullable?
        end
        return !a.nullable?
      end

      def post_verify
        Domgen.error("Routing key #{self.name} on #{self.imit_attribute.attribute.qualified_name} specifies graph '#{self.graph.name}' that is not filtered.") unless self.graph.filtered?
        Domgen.error("Routing key #{self.name} on #{self.imit_attribute.attribute.qualified_name} specifies graph '#{self.graph.name}' that entity is not currently part of.") unless self.graph.included_entities.include?(self.imit_attribute.attribute.entity.qualified_name)

        if attribute_name?
          Domgen.error("Routing key #{self.name} on #{self.imit_attribute.attribute.qualified_name} specifies attribute_name when attribute is not a reference or inverse reference") unless reference? || inverse_start?
        end

        if self.path.size > 0
          a = self.imit_attribute.attribute
          e = self.imit_attribute.attribute.reference? ? self.imit_attribute.attribute.referenced_entity : a.entity
          path.each do |path_key|
            is_inverse = is_inverse_path_element?(path_key)
            path_element = get_attribute_name_from_path_element?(path_key)

            if is_inverse
              candidates = e.arez.referencing_client_side_attributes.select { |attr| attr.inverse.name.to_s == path_element.to_s }
              Domgen.error("Path element '#{path_key}' specified for routing key #{name} on #{imit_attribute.attribute.name} does not reference a client side attribute") if candidates.empty?
              a = candidates[0]
              e = a.entity
              Domgen.error("Path element '#{path_key}' specified for routing key #{name} on #{imit_attribute.attribute.name} inverse reference is not immutable #{a.qualified_name}") unless a.immutable?
              Domgen.error("Path element '#{path_key}' specified for routing key #{name} on #{imit_attribute.attribute.name} inverse reference is not multiplicity :many. This has not been implemented yet") unless a.inverse.multiplicity == :many
            else
              Domgen.error("Path element '#{path_key}' specified for routing key #{name} on #{imit_attribute.attribute.name} does not refer to a valid attribute of #{e.qualified_name}") unless e.attribute_by_name?(path_element)
              a = e.attribute_by_name(path_element)
              Domgen.error("Path element '#{path_key}' specified for routing key #{name} on #{imit_attribute.attribute.name} references an attribute that is not a reference #{a.qualified_name}") unless a.reference?
              Domgen.error("Path element '#{path_key}' specified for routing key #{name} on #{imit_attribute.attribute.name} references an attribute that is not immutable #{a.qualified_name}") unless a.immutable?
              e = a.referenced_entity
            end
          end
        end
      end
    end

    class FilterParameter < Domgen.ParentedElement(:graph)
      attr_reader :filter_type

      include Characteristic

      def initialize(graph, filter_type, options, &block)
        @filter_type = filter_type
        super(graph, options, &block)
      end

      def name
        'FilterParameter'
      end

      def qualified_name
        "#{graph.qualified_name}$#{name}"
      end

      def immutable?
        @immutable.nil? ? false : @immutable
      end

      def immutable=(immutable)
        @immutable = immutable
      end

      def equiv?(other_filter_parameter)
        return false if other_filter_parameter.filter_type != self.filter_type
        return false if other_filter_parameter.collection_type != self.collection_type
        return false if other_filter_parameter.struct? && other_filter_parameter.referenced_struct.name != self.referenced_struct.name
        return false if other_filter_parameter.reference? && other_filter_parameter.referenced_entity.name != self.referenced_entity.name
        return true
      end

      def to_s
        "FilterParameter[#{self.qualified_name}]"
      end

      def characteristic_type_key
        filter_type
      end

      def characteristic_container
        graph
      end

      def struct_by_name(name)
        self.graph.application.repository.struct_by_name(name)
      end

      def entity_by_name(name)
        self.graph.application.repository.entity_by_name(name)
      end
    end
  end

  FacetManager.facet(:imit => [:ce, :arez, :gwt_rpc]) do |facet|
    facet.enhance(Repository) do
      include Domgen::Java::BaseJavaGenerator
      include Domgen::Java::JavaClientServerApplication

      attr_writer :schema_id

      def schema_id
        @schema_id || 1
      end

      def secured?
        @secured.nil? ? repository.keycloak? : !!@secured
      end

      attr_writer :secured

      def enable_entity_broker?
        @enable_entity_broker.nil? ? false : !!@enable_entity_broker
      end

      attr_writer :enable_entity_broker

      def generate_standard_endpoint?
        @generate_standard_endpoint.nil? ? true : !!@generate_standard_endpoint
      end

      attr_writer :generate_standard_endpoint

      def keycloak_client
        repository.keycloak.client_by_key(repository.gwt_rpc.keycloak_client)
      end

      attr_writer :client_component_package

      def client_component_package
        @client_component_package || "#{client_package}.components"
      end

      def client_ioc_package
        repository.gwt.client_ioc_package
      end

      attr_writer :server_comm_package

      def server_comm_package
        @server_comm_package || "#{server_package}.net"
      end

      attr_writer :client_comm_package

      def client_comm_package
        @client_comm_package || "#{client_package}.net"
      end

      def shared_comm_package
        @shared_comm_package || "#{shared_package}.net"
      end

      attr_writer :shared_comm_package

      def modules_package
        repository.gwt.modules_package
      end

      attr_writer :server_web_package

      def server_web_package
        @server_web_package || "#{server_package}.web"
      end

      java_artifact :endpoint, :web, :server, :imit, '#{repository.name}ReplicantEndpoint'
      java_artifact :abstract_endpoint, :web, :server, :imit, 'Abstract#{repository.name}ReplicantEndpoint'
      java_artifact :gwt_client_session_context, :comm, :client, :imit, '#{repository.name}GwtSessionContext'
      java_artifact :gwt_client_session_context_impl, :comm, :client, :imit, '#{gwt_client_session_context_name}Impl'
      java_artifact :client_router, :comm, :client, :imit, '#{repository.name}ClientRouter'
      java_artifact :subscription_util, :comm, :client, :imit, '#{repository.name}SubscriptionUtil'
      java_artifact :system_constants, :comm, :shared, :imit, '#{repository.name}SchemaConstants'
      java_artifact :subscription_constants, :comm, :shared, :imit, '#{repository.name}SubscriptionConstants'
      java_artifact :entity_type_constants, :comm, :shared, :imit, '#{repository.name}EntityTypeConstants'
      java_artifact :schema_sting_fragment, :comm, :client, :imit, '#{repository.name}SystemSchemaFragment'
      java_artifact :schema_filter_tools, :comm, :client, :imit, '#{repository.name}FilterTools'
      java_artifact :system_metadata, :comm, :server, :imit, '#{repository.name}MetaData'
      java_artifact :session_manager, :comm, :server, :imit, '#{repository.name}SessionManagerImpl'
      java_artifact :message_broker_impl, :comm, :server, :imit, '#{repository.name}ReplicantMessageBrokerImpl'
      java_artifact :session_rest_service, :rest, :server, :imit, '#{repository.name}SessionRestService'
      java_artifact :server_router, :comm, :server, :imit, '#{repository.name}Router'
      java_artifact :jpa_encoder, :comm, :server, :imit, '#{repository.name}JpaEncoder'
      java_artifact :message_generator, :comm, :server, :imit, '#{repository.name}EntityMessageGenerator'
      java_artifact :change_recorder, :comm, :server, :imit, '#{repository.name}ChangeRecorder'
      java_artifact :change_recorder_impl, :comm, :server, :imit, '#{change_recorder_name}Impl'
      java_artifact :change_listener, :comm, :server, :imit, '#{repository.name}EntityChangeListener'
      java_artifact :replication_interceptor, :comm, :server, :imit, '#{repository.name}ReplicationInterceptor'
      java_artifact :graph_encoder, :comm, :server, :imit, '#{repository.name}GraphEncoder'
      java_artifact :graph_encoder_impl, :comm, :server, :imit, '#{graph_encoder_name}Impl'
      java_artifact :abstract_schema_test, :comm, :client, :imit, 'Abstract#{repository.name}SchemaTest'
      java_artifact :server_net_module, :test, :server, :imit, '#{repository.name}ImitNetModule', :sub_package => 'util'
      java_artifact :integration_module, :test, :server, :imit, '#{repository.name}IntegrationModule', :sub_package => 'util'

      attr_writer :include_standard_integration_test_module

      def include_standard_integration_test_module?
        @include_standard_integration_test_module.nil? ? true : !!@include_standard_integration_test_module
      end

      def abstract_session_context_impl_name
        qualified_abstract_session_context_impl_name.gsub(/^.*\.([^.]+)$/, '\1')
      end

      def qualified_abstract_session_context_impl_name
        "#{repository.service_by_name(self.session_context_service).ejb.qualified_service_name.gsub(/^(.*)\.([^.]+$)/, '\1.Abstract\2Impl')}"
      end

      def auto_register_change_listener=(auto_register_change_listener)
        @auto_register_change_listener = !!auto_register_change_listener
      end

      def auto_register_change_listener?
        @auto_register_change_listener.nil? ? true : @auto_register_change_listener
      end

      def graphs
        graph_map.values
      end

      def graph(name, options = {}, &block)
        Domgen::Imit::ReplicationGraph.new(self, name, options, &block)
      end

      def graph_by_name(name)
        graph = graph_map[name.to_s]
        Domgen.error("Unable to locate graph #{name}") unless graph
        graph
      end

      def graph_by_name?(name)
        !!graph_map[name.to_s]
      end

      def subscription_manager=(subscription_manager)
        Domgen.error('subscription_manager invalid. Expected to be in format DataModule.ServiceName') if self.subscription_manager.to_s.split('.').length != 2
        @subscription_manager = subscription_manager
      end

      def subscription_manager
        @subscription_manager || "#{self.imit_control_data_module}.#{repository.name}SubscriptionService"
      end

      def message_broker=(message_broker)
        Domgen.error('message_broker invalid. Expected to be in format DataModule.ServiceName') if self.message_broker.to_s.split('.').length != 2
        @message_broker = message_broker
      end

      def message_broker
        @message_broker || "#{self.imit_control_data_module}.#{repository.name}ReplicantMessageBroker"
      end

      def session_context_service=(session_context_service)
        Domgen.error('session_context_service invalid. Expected to be in format DataModule.SessionContext') if session_context_service.to_s.split('.').length != 2
        @session_context_service = session_context_service
      end

      def session_context_service
        @session_context_service || "#{self.imit_control_data_module}.#{repository.name}SessionContext"
      end

      def client_converger_service=(client_converger_service)
        Domgen.error('client_converger_service invalid. Expected to be in format DataModule.SessionContext') if client_converger_service.to_s.split('.').length != 2
        @client_converger_service = client_converger_service
      end

      def client_converger_service
        @client_converger_service || "#{self.imit_control_data_module}.#{repository.name}ContextConvergerService"
      end

      def imit_control_data_module=(imit_control_data_module)
        @imit_control_data_module = imit_control_data_module
      end

      def imit_control_data_module
        @imit_control_data_module || (self.repository.data_module_by_name?(self.repository.name) ? self.repository.name : Domgen.error('imit_control_data_module unspecified and unable to derive default.'))
      end

      def requires_session_context?
        graphs.any? do |graph|
          graph.external_data_load? ||
            graph.bulk_load? ||
            graph.filtered? ||
            (!graph.instance_root? && graph.cacheable? && graph.external_cache_management?) ||
            (graph.instance_root? && graph.inward_graph_links.any? { |graph_link| graph_link.auto? && repository.imit.graph_by_name(graph_link.target_graph).filtered? })
        end
      end

      def pre_complete
        if repository.jaxrs?
          repository.jaxrs.extensions << self.qualified_session_rest_service_name
        end
        if repository.ee?
          repository.ee.cdi_scan_excludes << 'replicant.**'
          repository.ee.cdi_scan_excludes << 'org.realityforge.replicant.**'
        end
        toprocess = []
        self.graphs.each do |graph|
          if graph.filter_parameter?
            if graph.filter_parameter.enumeration?
              graph.filter_parameter.enumeration.part_of_filter = true
            elsif graph.filter_parameter.struct?
              struct = graph.filter_parameter.referenced_struct
              toprocess << struct unless toprocess.include?(struct)
            end
          end
        end

        process_filter_structs([], toprocess)
      end

      def process_filter_structs(processed, toprocess)
        until toprocess.empty?
          struct = toprocess.pop
          process_filter_struct(processed, toprocess, struct)
        end
      end

      def process_filter_struct(processed, toprocess, struct)
        return if processed.include?(struct)
        struct.imit.part_of_filter = true
        struct.fields.select { |field| field.imit? }.each do |field|
          if field.enumeration?
            field.enumeration.imit.part_of_filter = true
          elsif field.struct?
            struct = field.referenced_struct
            toprocess << struct unless toprocess.include?(struct)
          end
        end
      end

      def pre_verify
        if repository.gwt_rpc?
          client =
            repository.keycloak.client_by_key?(repository.gwt_rpc.keycloak_client) ?
              repository.keycloak.client_by_key(repository.gwt_rpc.keycloak_client) :
              repository.keycloak.client(repository.gwt_rpc.keycloak_client)
          client.bearer_only = true
          client.redirect_uris.clear
          client.web_origins.clear
          prefix = repository.jaxrs? ? "/#{repository.jaxrs.path}" : '/api'
          client.protected_url_patterns << prefix + '/session/*'
        end
        if repository.gwt?
          repository.gwt.sting_includes << qualified_schema_sting_fragment_name
          repository.gwt.sting_includes << qualified_gwt_client_session_context_impl_name
        end

        repository.ejb.add_test_module(self.server_net_module_name, self.qualified_server_net_module_name) if repository.ejb?
        if self.graphs.size == 0
          Domgen.error('imit facet enabled but no graphs defined')
        end

        if requires_session_context?
          self.repository.service(self.session_context_service) unless self.repository.service_by_name?(self.session_context_service)
          self.repository.service_by_name(self.session_context_service).tap do |s|
            s.disable_facets_not_in(:ejb)
            s.ejb.generate_boundary = false
            repository.imit.graphs.select { |graph| graph.filtered? }.each do |graph|
              s.method("FilterMessageOfInterestIn#{graph.name}Graph") do |m|
                m.ejb.generate_base_test = false
                m.parameter(:Message, 'org.realityforge.replicant.server.EntityMessage')
                m.parameter(:Session, 'org.realityforge.replicant.server.transport.ReplicantSession')
                if graph.instance_root?
                  entity = repository.entity_by_name(graph.instance_root)
                  m.parameter("#{entity.name}#{entity.primary_key.name}", entity.primary_key.jpa.non_primitive_java_type)
                end
                m.parameter(:Filter, graph.filter_parameter.filter_type, filter_options(graph)) if graph.filter_parameter?

                if graph.filtered?
                  graph.routing_keys.each do |routing_key|
                    options =
                      {
                        :collection_type => routing_key.multivalued? ? :sequence : :none,
                        :nullable => !graph.instance_root? || !(routing_key.imit_attribute.attribute.entity.qualified_name == graph.instance_root)
                      }
                    target_attribute = routing_key.target_attribute
                    options[:referenced_entity] = target_attribute.referenced_entity if target_attribute.reference?
                    options[:referenced_struct] = target_attribute.referenced_struct if target_attribute.struct?
                    m.parameter(routing_key.name.to_s.gsub('_', ''), target_attribute.attribute_type, options)
                  end
                end

                m.returns('org.realityforge.replicant.server.EntityMessage', :nullable => true)
              end
            end

            repository.imit.graphs.each do |graph|
              if !graph.instance_root?
                if graph.cacheable? && graph.external_cache_management?
                  s.method("Get#{graph.name}CacheKey") do |m|
                    m.ejb.generate_base_test = false
                    m.returns(:text)
                  end
                end
                if graph.filter_parameter? && !graph.filter_parameter.immutable?
                  s.method("CollectForFilterChange#{graph.name}") do |m|
                    m.parameter(:Session, 'org.realityforge.replicant.server.transport.ReplicantSession')
                    m.parameter(:Address, 'org.realityforge.replicant.server.ChannelAddress')
                    m.parameter(:OriginalFilter, graph.filter_parameter.filter_type, filter_options(graph))
                    m.parameter(:CurrentFilter, graph.filter_parameter.filter_type, filter_options(graph))
                  end
                end
                if graph.external_data_load? || graph.filtered?
                  s.method("Collect#{graph.name}") do |m|
                    m.parameter(:Address, 'org.realityforge.replicant.server.ChannelAddress')
                    m.parameter(:ChangeSet, 'org.realityforge.replicant.server.ChangeSet')
                    m.parameter(:Filter, graph.filter_parameter.filter_type, filter_options(graph)) if graph.filter_parameter?
                  end
                end
              else
                if graph.bulk_load?
                  s.method("BulkCollectDataFor#{graph.name}") do |m|
                    m.ejb.generate_base_test = false
                    m.parameter(:Session, 'org.realityforge.replicant.server.transport.ReplicantSession')
                    m.parameter(:Address, 'org.realityforge.replicant.server.ChannelAddress', :collection_type => :sequence)
                    m.parameter(:Filter, graph.filter_parameter.filter_type, filter_options(graph)) if graph.filter_parameter?
                    m.boolean(:ExplicitSubscribe)
                  end
                end
                if graph.filter_parameter?
                  unless graph.filter_parameter.immutable?
                    s.method("CollectForFilterChange#{graph.name}") do |m|
                      m.parameter(:Session, 'org.realityforge.replicant.server.transport.ReplicantSession')
                      m.parameter(:ChangeSet, 'org.realityforge.replicant.server.ChangeSet')
                      m.parameter(:Address, 'org.realityforge.replicant.server.ChannelAddress')
                      m.reference(graph.instance_root, :name => :Entity)
                      m.parameter(:OriginalFilter, graph.filter_parameter.filter_type, filter_options(graph))
                      m.parameter(:CurrentFilter, graph.filter_parameter.filter_type, filter_options(graph))
                    end
                    if graph.bulk_load?
                      s.method("BulkCollectDataFor#{graph.name}Update") do |m|
                        m.ejb.generate_base_test = false
                        m.parameter(:Session, 'org.realityforge.replicant.server.transport.ReplicantSession')
                        m.parameter(:Address, 'org.realityforge.replicant.server.ChannelAddress', :collection_type => :sequence)
                        m.parameter(:OriginalFilter, graph.filter_parameter.filter_type, filter_options(graph))
                        m.parameter(:CurrentFilter, graph.filter_parameter.filter_type, filter_options(graph))
                      end
                    end
                  end
                end
                if graph.filtered?
                  graph.reachable_entities.collect { |n| repository.entity_by_name(n) }.select { |entity| entity.imit? && entity.concrete? }.each do |entity|
                    outgoing_links = entity.referencing_attributes.select { |a| a.arez? && a.inverse.imit.traversable? && a.inverse.imit.replication_edges.include?(graph.name) }
                    outgoing_links.each do |a|
                      if a.inverse.multiplicity == :many
                        s.method("Get#{a.inverse.attribute.qualified_name.gsub('.', '')}In#{graph.name}Graph") do |m|
                          m.ejb.generate_base_test = false
                          m.reference(a.referenced_entity.qualified_name, :name => :Entity)
                          m.parameter(:Filter, graph.filter_parameter.filter_type, filter_options(graph)) if graph.filter_parameter?
                          m.returns(:reference, :referenced_entity => a.entity.qualified_name, :collection_type => :sequence)
                        end
                      elsif a.inverse.multiplicity == :one || a.inverse.multiplicity == :zero_or_one
                        s.method("Get#{a.inverse.attribute.qualified_name.gsub('.', '')}In#{graph.name}Graph") do |m|
                          m.ejb.generate_base_test = false
                          m.reference(a.referenced_entity.qualified_name, :name => :Entity)
                          m.parameter(:Filter, graph.filter_parameter.filter_type, filter_options(graph)) if graph.filter_parameter?
                          m.returns(:reference, :referenced_entity => a.entity.qualified_name, :nullable => (a.inverse.multiplicity == :zero_or_one))
                        end
                      end
                    end
                  end
                end
              end
            end

            processed = []
            repository.imit.graphs.select { |g| g.instance_root? }.collect { |g| g.inward_graph_links.select { |graph_link| graph_link.auto? } }.flatten.each do |graph_link|
              source_graph = repository.imit.graph_by_name(graph_link.source_graph)
              target_graph = repository.imit.graph_by_name(graph_link.target_graph)
              next unless target_graph.filtered?
              key = "#{graph_link.source_graph}=>#{graph_link.target_graph}"
              next if processed.include?(key)
              processed << key
              instance_root = repository.entity_by_name(target_graph.instance_root)

              if target_graph.filter_parameter?
                s.method(:"ShouldFollowLinkFrom#{graph_link.source_graph}To#{target_graph.name}") do |m|
                  m.reference(instance_root.qualified_name, :name => :Entity)
                  m.parameter(:Filter, source_graph.filter_parameter.filter_type, filter_options(source_graph))
                  m.returns(:boolean)
                end

                s.method(:"GetLinksToUpdateFor#{graph_link.source_graph}To#{target_graph.name}") do |m|
                  m.reference(repository.entity_by_name(source_graph.instance_root).qualified_name, :name => :Entity) if source_graph.instance_root?
                  m.parameter(:Filter, source_graph.filter_parameter.filter_type, filter_options(source_graph))
                  m.returns(:reference, :referenced_entity => instance_root, :collection_type => :sequence)
                end
              end
            end
          end
        end

        self.repository.service(self.subscription_manager) unless self.repository.service_by_name?(self.subscription_manager)
        self.repository.service_by_name(self.subscription_manager).tap do |s|
          s.disable_facets_not_in(:ejb)
          s.ejb.bind_in_tests = false
          s.ejb.generate_base_test = false

          s.method(:RemoveClosedSessions, 'ejb.schedule.hour' => '*', 'ejb.schedule.minute' => '*', 'ejb.schedule.second' => '30')
          s.method(:RemoveAllSessions)
          s.method(:PingSessions, 'ejb.schedule.hour' => '*', 'ejb.schedule.minute' => '*', 'ejb.schedule.second' => '15,45')
        end

        self.repository.service(self.message_broker) unless self.repository.service_by_name?(self.message_broker)
        self.repository.service_by_name(self.message_broker).tap do |s|
          s.disable_facets_not_in(:ejb)
          s.ejb.bind_in_tests = false
          s.ejb.generate_base_test = false

          s.method(:ProcessPendingSessions, 'ejb.schedule.hour' => '*', 'ejb.schedule.minute' => '*', 'ejb.schedule.second' => '*')
        end

        repository.data_modules.select { |data_module| data_module.ejb? }.each do |data_module|
          data_module.services.select { |service| service.ejb? && service.ejb.generate_boundary? }.each do |service|
            service.ejb.boundary_annotations << 'org.realityforge.replicant.server.ee.Replicate'
          end
        end
      end

      def post_complete
        index = 0
        repository.data_modules.select { |data_module| data_module.imit? }.each do |data_module|
          data_module.entities.each do |entity|
            if entity.imit? && entity.concrete?
              entity.imit.transport_id = index
              index += 1
            end
          end
        end
        repository.imit.graphs.select(&:instance_root?).each do |graph|
          entity_list = [repository.entity_by_name(graph.instance_root)]
          while entity_list.size > 0
            entity = entity_list.pop
            unless graph.reachable_entities.include?(entity.qualified_name.to_s)
              graph.reachable_entities << entity.qualified_name.to_s
              entity.referencing_attributes.each do |a|
                if a.imit? && a.inverse.imit.traversable? && !a.inverse.imit.exclude_edges.include?(graph.name)
                  a.inverse.imit.replication_edges = a.inverse.imit.replication_edges + [graph.name]
                  Domgen.error("#{a.qualified_name} is not immutable but is on path in graph #{graph.name}") unless a.immutable?
                  entity_list << a.entity unless graph.reachable_entities.include?(a.entity.qualified_name.to_s)
                end
              end
            end
          end
        end
        repository.imit.graphs.each(&:post_verify)
      end

      private

      def filter_options(graph)
        filter_options = {}
        if graph.filter_parameter?
          filter_options =
            {
              :collection_type => graph.filter_parameter.collection_type,
              :nullable => graph.filter_parameter.nullable?
            }
          filter_options[:referenced_entity] = graph.filter_parameter.referenced_entity if graph.filter_parameter.reference?
          filter_options[:referenced_struct] = graph.filter_parameter.referenced_struct if graph.filter_parameter.struct?
        end
        filter_options
      end

      def register_graph(name, graph)
        graph_map[name.to_s] = graph
      end

      def graph_map
        @graphs ||= {}
      end
    end

    facet.enhance(DataModule) do
      include Domgen::Java::BaseJavaGenerator
      include Domgen::Java::ImitJavaPackage

      java_artifact :mapper, :entity, :client, :imit, '#{data_module.name}Mapper'
    end

    facet.enhance(Service) do
      include Domgen::Java::BaseJavaGenerator
    end

    facet.enhance(Parameter) do
      include Domgen::Java::ImitJavaCharacteristic

      def environmental?
        parameter.gwt_rpc? && parameter.gwt_rpc.environmental?
      end

      protected

      def characteristic
        parameter
      end
    end

    facet.enhance(Result) do
      include Domgen::Java::ImitJavaCharacteristic

      protected

      def characteristic
        result
      end
    end

    facet.enhance(Exception) do
      include Domgen::Java::BaseJavaGenerator

      java_artifact :name, :service, :client, :imit, '#{exception.name}Exception'
    end

    facet.enhance(Entity) do
      include Domgen::Java::BaseJavaGenerator

      def transport_id
        Domgen.error('Attempted to invoke transport_id on abstract entity') if entity.abstract?
        @transport_id
      end

      def transport_id=(transport_id)
        Domgen.error('Attempted to assign transport_id on abstract entity') if entity.abstract?
        @transport_id = transport_id
      end

      def interfaces
        @interfaces ||= []
      end

      def replication_root?
        entity.data_module.repository.imit.graphs.any? { |g| g.instance_root? && g.instance_root.to_s == entity.qualified_name.to_s }
      end

      def associated_instance_root_graphs
        entity.data_module.repository.imit.graphs.select { |g| g.instance_root? && g.instance_root.to_s == entity.qualified_name.to_s }
      end

      def associated_type_graphs
        entity.data_module.repository.imit.graphs.select { |g| !g.instance_root? && g.type_roots.include?(entity.qualified_name.to_s) }
      end

      def replicate(graph, replication_type)
        Domgen.error("#{replication_type.inspect} is not of a known type") unless [:instance, :type].include?(replication_type)
        graph = entity.data_module.repository.imit.graph_by_name(graph)
        k = entity.qualified_name
        Domgen.error("Attempting to override instance graph root '#{graph.instance_root}' with '#{k}' is not allowed.") if :instance == replication_type && graph.instance_root?
        graph.instance_root = k if :instance == replication_type
        graph.type_roots.concat([k.to_s]) if :type == replication_type
      end

      def test_create_default(defaults)
        (@test_create_defaults ||= []) << Domgen::Imit::DefaultValues.new(entity, defaults)
      end

      def test_create_defaults
        @test_create_defaults.nil? ? [] : @test_create_defaults.dup
      end

      #
      # subgraph_roots are parts of the graph that are exposed by encoder
      # Useful when collecting entities when a filter is present
      #
      def subgraph_roots
        @subgraph_roots || []
      end

      def subgraph_roots=(subgraph_roots)
        Domgen.error('subgraph_roots expected to be an array') unless subgraph_roots.is_a?(Array)
        subgraph_roots.each do |subgraph_root|
          graph = entity.data_module.repository.imit.graph_by_name(subgraph_root)
          Domgen.error("subgraph_roots specifies a non graph #{subgraph_root}") unless graph
          Domgen.error("subgraph_roots specifies a non-instance graph #{subgraph_root}") unless graph.instance_root?
          Domgen.error("subgraph_roots specifies a non-filtered graph #{subgraph_root}") unless graph.filtered?
        end
        @subgraph_roots = subgraph_roots
      end

      def replication_graphs
        entity.data_module.repository.imit.graphs.select do |graph|
          (graph.instance_root? && graph.reachable_entities.include?(entity.qualified_name.to_s)) ||
            (!graph.instance_root? && graph.type_roots.include?(entity.qualified_name.to_s)) ||
            entity.attributes.any? { |a| a.imit? && a.imit.routing_keys.any? { |routing_key| routing_key.graph.name.to_s == graph.name.to_s } }
        end
      end

      def pre_verify
        if entity.data_module.repository.imit.auto_register_change_listener? && entity.jpa?
          entity.jpa.entity_listeners << entity.data_module.repository.imit.qualified_change_listener_name
        end
      end
    end

    facet.enhance(Attribute) do
      def eager?
        !lazy?
      end

      def lazy=(lazy)
        Domgen.error("Attempted to make non-reference #{attribute.qualified_name} lazy") if lazy && !attribute.reference?
        @lazy = lazy
      end

      def lazy?
        attribute.reference? && (@lazy.nil? ? false : @lazy)
      end

      def filter_in_graphs=(filter_in_graphs)
        Domgen.error('filter_in_graphs should be an array of symbols') unless filter_in_graphs.is_a?(Array) && filter_in_graphs.all? { |m| m.is_a?(Symbol) }
        Domgen.error('filter_in_graphs should only contain valid graphs') unless filter_in_graphs.all? { |m| attribute.entity.data_module.repository.imit.graph_by_name(m) }
        filter_in_graphs.each do |graph|
          routing_key(graph)
        end
      end

      def routing_keys_map
        @routing_keys ||= {}
      end

      def routing_keys
        routing_keys_map.values
      end

      def routing_key(graph, options = {})
        params = options.dup
        name = params.delete(:name) || attribute.qualified_name.gsub('.', '_')
        routing_keys_map["#{graph}#{name}"] = Domgen::Imit::RoutingKey.new(self, name, graph, params)
      end

      def auto_graph_links
        graph_links_map.values.select { |graph_link| graph_link.auto? }
      end

      def graph_links
        graph_links_map.values
      end

      def graph_link(source_graph, target_graph, options = {}, &block)
        key = "#{source_graph}->#{target_graph}"
        Domgen.error("Graph link already defined between #{source_graph} and #{target_graph} on attribute '#{attribute.qualified_name}'") if graph_links_map[key]
        graph_links_map[key] = Domgen::Imit::GraphLink.new(self, "#{key}:#{attribute.qualified_name}", source_graph, target_graph, options, &block)
      end

      include Domgen::Java::ImitJavaCharacteristic

      def post_verify
        self.graph_links.each do |graph_link|
          graph_link.post_verify
        end
        self.routing_keys.each do |routing_key|
          routing_key.post_verify
        end
        self.attribute.inverse.imit.exclude_edges.each do |graph_name|
          a = self.attribute
          repository_imit_facet = a.entity.data_module.repository.imit
          Domgen.error("#{a.qualified_name} has specified an inverse.imit.exclude_edges value for graph named '#{graph_name}' but no such graph exists") unless repository_imit_facet.graph_by_name?(graph_name)
          Domgen.error("#{a.qualified_name} has specified an inverse.imit.exclude_edges value for graph named '#{graph_name}' but graph is not an instance graph") unless repository_imit_facet.graph_by_name(graph_name).instance_root?
        end if self.attribute.reference?
      end

      protected

      def graph_links_map
        @graph_links ||= {}
      end

      def characteristic
        attribute
      end
    end

    facet.enhance(InverseElement) do
      def traversable=(traversable)
        Domgen.error("traversable #{traversable} is invalid") unless inverse.class.inverse_traversable_types.include?(traversable)
        @traversable = traversable
      end

      def traversable?
        @traversable.nil? ? (self.inverse.traversable? && self.inverse.attribute.referenced_entity.imit?) : @traversable
      end

      def exclude_edges
        @exclude_edges ||= []
      end

      def exclude_edges=(exclude_edges)
        @exclude_edges = exclude_edges
      end

      # Replication edges represent graphs that must be subscribed to when the containing entity is subscribed
      def replication_edges=(replication_edges)
        Domgen.error('replication_edges should be an array of symbols') unless replication_edges.is_a?(Array) && replication_edges.all? { |m| m.is_a?(Symbol) }
        Domgen.error('replication_edges should only be set when traversable?') unless inverse.traversable?
        Domgen.error('replication_edges should only contain valid graphs') unless replication_edges.all? { |m| inverse.attribute.entity.data_module.repository.imit.graph_by_name(m) }
        @replication_edges = replication_edges
      end

      def replication_edges
        @replication_edges || []
      end

      def pre_complete
        if self.inverse.traversable? && !self.inverse.attribute.referenced_entity.imit?
          self.inverse.disable_facet(:imit)
        end
      end
    end

    facet.enhance(EnumerationSet) do
      def part_of_filter?
        !!@part_of_filter
      end

      attr_writer :part_of_filter
    end

    facet.enhance(Struct) do
      def part_of_filter?
        !!@part_of_filter
      end

      attr_writer :part_of_filter

      def filter_for_graph(graph_key, options = {})
        struct.data_module.repository.imit.graph_by_name(graph_key).filter(:struct, options.merge(:referenced_struct => struct.qualified_name))
      end
    end
  end
end


text:
package io.comhub.register.android.data.cache.serializer;

import io.comhub.register.android.data.ApplicationTestCase;
import io.comhub.register.android.data.user.entity.UserEntity;
import org.junit.Before;
import org.junit.Test;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

public class JsonSerializerTest extends ApplicationTestCase {

  private static final String JSON_RESPONSE = "{\n"
    + "    \"id\": 1,\n"
    + "    \"cover_url\": \"http://www.android10.org/myapi/cover_1.jpg\",\n"
    + "    \"full_name\": \"Simon Hill\",\n"
    + "    \"description\": \"Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem.\\n\\nInteger tincidunt ante vel ipsum. Praesent blandit lacinia erat. Vestibulum sed magna at nunc commodo placerat.\\n\\nPraesent blandit. Nam nulla. Integer pede justo, lacinia eget, tincidunt eget, tempus vel, pede.\",\n"
    + "    \"followers\": 7484,\n"
    + "    \"email\": \"jcooper@babbleset.edu\"\n"
    + "}";

  private JsonSerializer jsonSerializer;

  @Before
  public void setUp() {
    jsonSerializer = new JsonSerializer();
  }

  @Test
  public void testSerializeHappyCase() {
    UserEntity userEntityOne = jsonSerializer.deserialize(JSON_RESPONSE);
    String jsonString = jsonSerializer.serialize(userEntityOne);
    UserEntity userEntityTwo = jsonSerializer.deserialize(jsonString);

    assertThat(userEntityOne.getUserId(), is(userEntityTwo.getUserId()));
    assertThat(userEntityOne.getFullname(), is(equalTo(userEntityTwo.getFullname())));
    assertThat(userEntityOne.getFollowers(), is(userEntityTwo.getFollowers()));
  }

  @Test
  public void testDesearializeHappyCase() {
    UserEntity userEntity = jsonSerializer.deserialize(JSON_RESPONSE);

    assertThat(userEntity.getUserId(), is(1));
    assertThat(userEntity.getFullname(), is("Simon Hill"));
    assertThat(userEntity.getFollowers(), is(7484));
  }
}