text:
// source:

package test.junit.vfs;

import junit.framework.Test;
import junit.framework.TestSuite;
import nl.uva.vlet.Global;
import nl.uva.vlet.vrl.VRL;
import nl.uva.vlet.vrs.ServerInfo;
import nl.uva.vlet.vrs.VRSContext;
import test.junit.TestSettings;

/**
 * Test SRB case
 *
 * TestSuite uses testVFS class to tests SRM implementation.
 *
 * @author P.T. de Boer
 */
public class testSRMAMC extends testSRM
{
    public static VRL getTestLocation()
    {
        return TestSettings.getTestLocation(TestSettings.VFS_SRM_AMC_LOCATION);
    }

    @Override
    public VRL getRemoteLocation()
    {
        return getTestLocation();
    }

    public VRL getOtherRemoteLocation()
    {
        // Use SRM Nikhef as "other"
        return TestSettings.getTestLocation(TestSettings.VFS_SRM_DPM_NIKHEF_LOCATION);
    }

    boolean getTestEncodedPaths()
    {
        return false;
    }

    // ====
    // MAIN
    // ===

    public static Test suite()
    {

        testVFS.staticCheckProxy();
        // Global.setPassiveMode(true);

        // Create ServerInfo registry
        ServerInfo info = null;

        try
        {
            info = VRSContext.getDefault().getServerInfoFor(getTestLocation(), true);
            info.store();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        if (info == null)
            Global.errorPrintf("testSRM", "Warning: No SRM Server configuration found for:%s\n",getTestLocation());

        return new TestSuite(testSRMAMC.class);
    }

    public static void main(String args[])
    {
        junit.textui.TestRunner.run(suite());
    }

}


text:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.Enumeration;
using Windows.Devices.Spi;
using Windows.UI;

namespace TheBox
{
    public class DotStarStrip
    {
        private const int SpiChipSelectLine = 0;
        private SpiDevice spiDevice;
        public string SpiControllerName { get; private set; }
        public int PixelCount { get; private set; }
        private readonly SpiConnectionSettings settings = new SpiConnectionSettings(SpiChipSelectLine)
        {
            ClockFrequency = 10000000,
            Mode = SpiMode.Mode3,
            DataBitLength = 8
        };

        private byte[] startFrame = { 0, 0, 0, 0 };
        private byte[] endFrame;

        private byte[] spiDataBytes;

        public List<Color> strip;

        public DotStarStrip(int numberOfLeds, string spiPort)
        {
            PixelCount = numberOfLeds;
            SpiControllerName = spiPort;
            int endFrameSize = PixelCount / 2 + 1;
            endFrame = new byte[endFrameSize];
            strip = GetResetPixels();
            spiDataBytes = new byte[startFrame.Length + PixelCount * 4 + endFrame.Length];
            for (int i = 0; i < startFrame.Length; i++)
            {
                spiDataBytes[i] = startFrame[i];
            }
        }

        public async Task Begin()
        {
            spiDevice = await GetSpiDevice();
        }

        public List<Color> GetResetPixels()
        {
            return GetResetPixels(Colors.Black);
        }

        public List<Color> GetResetPixels(Color color)
        {
            List<Color> pixels = new List<Color>();
            for (int i = 0; i < PixelCount; i++)
            {
                pixels.Add(color);
            }
            return pixels;
        }

        public void ResetPixels()
        {
            ResetPixels(Colors.Black);
        }

        public void ResetPixels(Color color)
        {
            for (int i = 0; i < strip.Count; i++)
            {
                strip[i] = color;
            }
        }

        public void SendPixels()
        {
            SendPixels(strip);
        }

        public void SendPixels(List<Color> pixels)
        {
            int i = 4;
            for (int j = 0; j < pixels.Count; j++)
            {
                spiDataBytes[i] = (byte)(0xE0 | (byte)(pixels[j].A >> 3));
                i++;
                spiDataBytes[i] = (byte)(pixels[j].B >> 1);
                i++;
                spiDataBytes[i] = (byte)(pixels[j].G >> 1);
                i++;
                spiDataBytes[i] = (byte)(pixels[j].R >> 1);
                i++;
            }
            for (int j = 0; j < endFrame.Length; j++)
            {
                spiDataBytes[i] = endFrame[j];
                i++;
            }
            if (spiDevice != null)
            {
                spiDevice.Write(spiDataBytes);
            }
        }

        // de optimized version
        //public void SendPixels(List<Color> pixels)
        //{
        //    List<byte> spiDataBytes = new List<byte>();
        //    spiDataBytes.AddRange(startFrame);
        //    foreach (Color pixel in pixels)
        //    {
        //        //spiDataBytes.Add(0xE0 | 0x1F);
        //        spiDataBytes.Add((byte)(0xE0 | (byte)(pixel.A >> 3)));
        //        spiDataBytes.Add((byte)(pixel.B >> 1));
        //        spiDataBytes.Add((byte)(pixel.G >> 1));
        //        spiDataBytes.Add((byte)(pixel.R >> 1));
        //    }
        //    spiDataBytes.AddRange(endFrame);
        //    spiDevice.Write(spiDataBytes.ToArray());
        //}

        public void SendPixels(List<byte> pixels)
        {
            List<byte> spiDataBytes = new List<byte>();
            spiDataBytes.AddRange(startFrame);

            foreach (byte pixel in pixels)
            {
                spiDataBytes.Add(0xE0 | 0x1F);
                spiDataBytes.Add((byte)(pixel >> 1));
                spiDataBytes.Add((byte)(pixel >> 1));
                spiDataBytes.Add((byte)(pixel >> 1));
            }
            spiDataBytes.AddRange(endFrame);
            spiDevice.Write(spiDataBytes.ToArray());
        }

        private async Task<SpiDevice> GetSpiDevice()
        {
            string spiSelector = SpiDevice.GetDeviceSelector(SpiControllerName);
            DeviceInformationCollection devicesInfo = await DeviceInformation.FindAllAsync(spiSelector);
            return await SpiDevice.FromIdAsync(devicesInfo[0].Id, settings);
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
package ua.com.fielden.platform.entity.proxy;

import static javassist.util.proxy.ProxyFactory.isProxyClass;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static ua.com.fielden.platform.entity.query.fluent.EntityQueryUtils.fetch;
import static ua.com.fielden.platform.entity.query.fluent.EntityQueryUtils.fetchAll;
import static ua.com.fielden.platform.entity.query.fluent.EntityQueryUtils.fetchKeyAndDescOnly;
import static ua.com.fielden.platform.entity.query.fluent.EntityQueryUtils.fetchOnly;
import static ua.com.fielden.platform.entity.query.fluent.EntityQueryUtils.from;
import static ua.com.fielden.platform.entity.query.fluent.EntityQueryUtils.select;
import static ua.com.fielden.platform.reflection.Reflector.isPropertyProxied;
import static ua.com.fielden.platform.types.try_wrapper.TryWrapper.Try;

import java.math.BigDecimal;
import java.util.stream.Stream;

import org.junit.Test;

import ua.com.fielden.platform.entity.AbstractEntity;
import ua.com.fielden.platform.entity.query.fluent.fetch;
import ua.com.fielden.platform.entity.query.model.EntityResultQueryModel;
import ua.com.fielden.platform.reflection.Reflector;
import ua.com.fielden.platform.sample.domain.ITgBogie;
import ua.com.fielden.platform.sample.domain.ITgVehicle;
import ua.com.fielden.platform.sample.domain.TgAuthor;
import ua.com.fielden.platform.sample.domain.TgBogie;
import ua.com.fielden.platform.sample.domain.TgBogieLocation;
import ua.com.fielden.platform.sample.domain.TgFuelType;
import ua.com.fielden.platform.sample.domain.TgFuelUsage;
import ua.com.fielden.platform.sample.domain.TgOrgUnit1;
import ua.com.fielden.platform.sample.domain.TgOrgUnit2;
import ua.com.fielden.platform.sample.domain.TgOrgUnit3;
import ua.com.fielden.platform.sample.domain.TgOrgUnit4;
import ua.com.fielden.platform.sample.domain.TgOrgUnit5;
import ua.com.fielden.platform.sample.domain.TgPersonName;
import ua.com.fielden.platform.sample.domain.TgReVehicleModel;
import ua.com.fielden.platform.sample.domain.TgTimesheet;
import ua.com.fielden.platform.sample.domain.TgVehicle;
import ua.com.fielden.platform.sample.domain.TgVehicleFinDetails;
import ua.com.fielden.platform.sample.domain.TgVehicleMake;
import ua.com.fielden.platform.sample.domain.TgVehicleModel;
import ua.com.fielden.platform.sample.domain.TgWagon;
import ua.com.fielden.platform.sample.domain.TgWagonSlot;
import ua.com.fielden.platform.sample.domain.TgWorkshop;
import ua.com.fielden.platform.security.user.User;
import ua.com.fielden.platform.security.user.UserAndRoleAssociation;
import ua.com.fielden.platform.security.user.UserRole;
import ua.com.fielden.platform.test_config.AbstractDaoTestCase;
import ua.com.fielden.platform.types.Money;
import ua.com.fielden.platform.types.either.Either;
import ua.com.fielden.platform.types.either.Left;

public class EntityProxyLoadingTest extends AbstractDaoTestCase {

    private final ITgBogie coBogie = getInstance(ITgBogie.class);
    private final ITgVehicle coVehicle = getInstance(ITgVehicle.class);

    private static void shouldNotBeProxy(Class<? extends AbstractEntity<?>> entityClass) {
        assertFalse("Should not be proxy", isProxyClass(entityClass));
    }

    private static void shouldBeProxy(final AbstractEntity<?> entity, final String propName) {
        assertTrue("Should be proxy", Reflector.isPropertyProxied(entity, propName));
    }

    private static void shouldNotBeProxy(final AbstractEntity<?> entity, final String propName) {
        assertFalse("Should not be proxy", Reflector.isPropertyProxied(entity, propName));
    }

    ///////////////////////////// primitive prop //////////////////////////////
    @Test
    public void not_null_primitive_property_outside_fetch_model_should_be_proxied() {
        final EntityResultQueryModel<TgVehicle> model = select(TgVehicle.class).where().prop("key").eq().val("CAR2").model();
        final TgVehicle vehicle = coVehicle.getEntity(from(model).with(fetch(TgVehicle.class).without("desc")).model());
        shouldBeProxy(vehicle, "desc");
    }

    @Test
    public void not_null_calc_property_outside_fetch_model_should_be_proxied() {
        final EntityResultQueryModel<TgVehicle> model = select(TgVehicle.class).where().prop("key").eq().val("CAR2").model();
        final TgVehicle vehicle = coVehicle.getEntity(from(model).model());
        shouldBeProxy(vehicle, "constValueProp");
    }

    ///////////////////////////// usual entity prop //////////////////////////////
    @Test
    public void not_null_entity_property_outside_fetch_model_should_be_proxied() {
        final EntityResultQueryModel<TgVehicle> model = select(TgVehicle.class).where().prop("key").eq().val("CAR2").model();
        final TgVehicle vehicle = coVehicle.getEntity(from(model).model());
        assertNotNull("Should be not null", vehicle.getReplacedBy().getId());
        shouldBeProxy(vehicle.getReplacedBy(), "model");
        shouldBeProxy(vehicle.getReplacedBy(), "key");
    }

    @Test
    public void null_entity_property_outside_fetch_model_should_be_also_proxied() {
        final EntityResultQueryModel<TgVehicle> model = select(TgVehicle.class).where().prop("key").eq().val("CAR1").model();
        final TgVehicle vehicle = coVehicle.getEntity(from(model).model());
        assertNull("Should be null", vehicle.getReplacedBy());
    }

    @Test
    public void null_entity_property_within_fetch_model_should_not_be_proxied() {
        final EntityResultQueryModel<TgVehicle> model = select(TgVehicle.class).where().prop("key").eq().val("CAR1").model();
        final TgVehicle vehicle = coVehicle.getEntity(from(model).with(fetch(TgVehicle.class).with("replacedBy")).model());
        shouldNotBeProxy(vehicle, "replacedBy");
        assertNull(vehicle.getReplacedBy());
    }

    @Test
    public void not_null_entity_property_within_fetch_model_should_not_be_proxied() {
        final EntityResultQueryModel<TgVehicle> model = select(TgVehicle.class).where().prop("key").eq().val("CAR2").model();
        final TgVehicle vehicle = coVehicle.getEntity(from(model).with(fetch(TgVehicle.class).with("replacedBy")).model());
        shouldNotBeProxy(vehicle.getReplacedBy().getClass());
        shouldNotBeProxy(vehicle, "replacedBy");
        assertNotNull(vehicle.getReplacedBy());
    }

    ///////////////////////////// 1-2-1 entity prop (implicitly calculated prop) //////////////////////////////
    @Test
    public void not_null_121_property_outside_fetch_model_should_be_proxied() {
        final EntityResultQueryModel<TgVehicle> model = select(TgVehicle.class).where().prop("key").eq().val("CAR1").model();
        final TgVehicle vehicle = coVehicle.getEntity(from(model).model());
        shouldBeProxy(vehicle, "finDetails");
    }

    @Test
    public void null_121_property_outside_fetch_model_should_also_be_proxied() {
        final EntityResultQueryModel<TgVehicle> model = select(TgVehicle.class).where().prop("key").eq().val("CAR2").model();
        final TgVehicle vehicle = coVehicle.getEntity(from(model).model());
        shouldBeProxy(vehicle, "finDetails");
    }

    @Test
    public void not_null_121_property_within_fetch_model_should_not_be_proxied() {
        final EntityResultQueryModel<TgVehicle> model = select(TgVehicle.class).where().prop("key").eq().val("CAR1").model();
        final TgVehicle vehicle = coVehicle.getEntity(from(model).with(fetch(TgVehicle.class).with("finDetails")).model());
        shouldNotBeProxy(vehicle, "finDetails");
        shouldNotBeProxy(vehicle.getFinDetails().getClass());
        assertNotNull(vehicle.getFinDetails());
    }

    @Test
    public void null_121_property_within_fetch_model_should_not_be_proxied() {
        final EntityResultQueryModel<TgVehicle> model = select(TgVehicle.class).where().prop("key").eq().val("CAR2").model();
        final TgVehicle vehicle = coVehicle.getEntity(from(model).with(fetch(TgVehicle.class).with("finDetails")).model());
        shouldNotBeProxy(vehicle, "finDetails");
        assertNull(vehicle.getFinDetails());
    }

    ///////////////////////////// calculated entity prop (explicitly calculated prop) //////////////////////////////
    @Test
    public void not_null_calculated_property_outside_fetch_model_should_be_proxied() {
        final EntityResultQueryModel<TgVehicle> model = select(TgVehicle.class).where().prop("key").eq().val("CAR2").model();
        final TgVehicle vehicle = coVehicle.getEntity(from(model).with(fetch(TgVehicle.class).with("finDetails")).model());
        shouldBeProxy(vehicle, "lastFuelUsage");
    }

    @Test
    public void not_null_calculated_property_within_fetch_model_should_not_be_proxied() {
        final EntityResultQueryModel<TgVehicle> model = select(TgVehicle.class).where().prop("key").eq().val("CAR2").model();
        final TgVehicle vehicle = coVehicle.getEntity(from(model).with(fetch(TgVehicle.class).with("lastFuelUsage")).model());
        shouldNotBeProxy(vehicle, "lastFuelUsage");
        assertNotNull(vehicle.getLastFuelUsage().getId());
    }

    ///////////////////////////// other //////////////////////////////
    @Test
    public void test_fetch_all_with_calc_prop() {
        final EntityResultQueryModel<TgVehicle> qry = select(TgVehicle.class).where().prop("key").eq().val("CAR2").model();
        final TgVehicle veh = coVehicle.getEntity(from(qry).with(fetchAll(TgVehicle.class).with("lastFuelUsage")).model());
        shouldNotBeProxy(veh, "replacedBy");
        shouldNotBeProxy(veh, "lastFuelUsage");
        shouldNotBeProxy(veh.getLastFuelUsage(), "vehicle");
        shouldNotBeProxy(veh.getLastFuelUsage().getVehicle(), "replacedBy");
    }

    @Test
    public void test_fetch_all_with_121_prop() {
        final EntityResultQueryModel<TgVehicle> qry = select(TgVehicle.class).where().prop("key").eq().val("CAR2").model();
        final TgVehicle veh = coVehicle.getEntity(from(qry).with(fetchAll(TgVehicle.class).with("finDetails", fetch(TgVehicleFinDetails.class))).model());
        shouldNotBeProxy(veh, "replacedBy");
        shouldNotBeProxy(veh, "finDetails");
    }

    @Test
    public void test_fetch_of_one_to_one_master_entity_model() {
        final EntityResultQueryModel<TgVehicle> qry = select(TgVehicle.class).where().prop("key").eq().val("CAR1").model();
        final TgVehicle veh = coVehicle.getEntity(from(qry).with(fetchAll(TgVehicle.class).with("finDetails", fetch(TgVehicleFinDetails.class))).model());
        shouldNotBeProxy(veh, "model");
        shouldNotBeProxy(veh, "finDetails");
        shouldNotBeProxy(veh.getFinDetails(), "key");
        shouldNotBeProxy(veh.getFinDetails().getKey(), "model");
    }

    @Test
    public void test_query_with_union_property_being_null() {
        final EntityResultQueryModel<TgBogie> qry = select(TgBogie.class).where().prop("key").eq().val("BOGIE2").model();
        TgBogie bogie = coBogie.getEntity(from(qry).with(fetch(TgBogie.class).with("location", fetch(TgBogieLocation.class).with("wagonSlot").with("workshop"))).model());
        shouldNotBeProxy(bogie, "location");
        assertNull(bogie.getLocation());
    }

    @Test
    public void test_query_for_correct_fetching_adjustment() {
        final EntityResultQueryModel<TgVehicle> qry = select(TgVehicle.class).
                where().prop("key").eq().val("CAR2").
                yield().prop("key").as("key").
                yield().prop("desc").as("desc").
                yield().prop("model").as("model").
                yield().prop("model.make").as("model.make").
                yield().prop("model.make.key").as("model.make.key").
                modelAsEntity(TgVehicle.class);
        final TgVehicle vehicle1 = coVehicle.getEntity(from(qry).with(fetch(TgVehicle.class).
                with("key").
                with("desc").
                with("model", fetchOnly(TgVehicleModel.class).
                        with("key").
                        with("make", fetchOnly(TgVehicleMake.class).
                                with("key")))).model());
        assertNotNull(vehicle1.getModel().getMake().getKey());
        assertNull(vehicle1.getReplacedBy());
    }

    @Test
    public void properties_with_id_only_proxy_values_can_be_updated_with_null_and_saved() {
        final ITgVehicle coVehicle = co$(TgVehicle.class);
        final TgVehicle vehicle = coVehicle.findByKey("CAR2");

        assertFalse(Reflector.isPropertyProxied(vehicle, "station"));

        assertNotNull(vehicle.getStation());
        assertTrue(vehicle.getStation().isIdOnlyProxy());
        assertFalse(vehicle.getProperty("station").isDirty());

        vehicle.setStation(null);
        assertTrue(vehicle.getProperty("station").isDirty());
        assertNull(vehicle.getStation());

        final TgVehicle savedVehicle = save(vehicle);
        assertNull(savedVehicle.getStation());
    }

    @Test
    public void properties_with_id_only_proxy_values_cannot_be_updated_with_non_null_values() {
        final ITgVehicle coVehicle = co$(TgVehicle.class);
        final TgVehicle vehicle = coVehicle.findByKey("CAR2");

        assertFalse(Reflector.isPropertyProxied(vehicle, "station"));

        assertNotNull(vehicle.getStation());
        assertTrue(vehicle.getStation().isIdOnlyProxy());
        assertFalse(vehicle.getProperty("station").isDirty());

        final EntityResultQueryModel<TgOrgUnit5> query = select(TgOrgUnit5.class).where().prop("name").eq().val("orgunit5_1").model();
        final TgOrgUnit5 station51 = co(TgOrgUnit5.class).getEntity(from(query).with(fetchAll(TgOrgUnit5.class)).model());

        final Either<Exception, TgVehicle> setStationResult = Try(() -> vehicle.setStation(station51));
        assertTrue(setStationResult instanceof Left);
        final Left<Exception, TgVehicle> setError = (Left<Exception, TgVehicle>) setStationResult;
        assertTrue(setError.value instanceof StrictProxyException);
    }

    @Test
    public void properties_that_could_have_id_only_proxy_values_but_are_null_can_be_updated_with_non_null_values() {
        final ITgVehicle coVehicle = co$(TgVehicle.class);
        final TgVehicle vehicle = coVehicle.findByKey("CAR1");

        assertFalse(Reflector.isPropertyProxied(vehicle, "station"));

        assertNull(vehicle.getStation());
        assertFalse(vehicle.getProperty("station").isDirty());

        final EntityResultQueryModel<TgOrgUnit5> query = select(TgOrgUnit5.class).where().prop("name").eq().val("orgunit5_1").model();
        final TgOrgUnit5 station51 = co(TgOrgUnit5.class).getEntity(from(query).with(fetchAll(TgOrgUnit5.class)).model());

        vehicle.setStation(station51);
        assertTrue(vehicle.getProperty("station").isDirty());
        assertEquals(station51, vehicle.getStation());

        final TgVehicle savedVehicle = save(vehicle);
        assertEquals(station51, savedVehicle.getStation());
    }

    @Test
    public void explicitly_unfetched_properties_of_entity_type_can_neither_be_accessed_nor_mutated() {
        final ITgVehicle coVehicle = co(TgVehicle.class);
        final fetch<TgVehicle> fetch = fetchKeyAndDescOnly(TgVehicle.class);
        final TgVehicle vehicle = coVehicle.findByKeyAndFetch(fetch, "CAR2");

        assertTrue(Reflector.isPropertyProxied(vehicle, "station"));

        final Either<Exception, TgOrgUnit5> getStationResult = Try(() -> vehicle.getStation());
        assertTrue(getStationResult instanceof Left);
        final Left<Exception, TgOrgUnit5> getError = (Left<Exception, TgOrgUnit5>) getStationResult;
        assertTrue(getError.value instanceof StrictProxyException);

        final Either<Exception, TgVehicle> setStationResult = Try(() -> vehicle.setStation(null));
        assertTrue(setStationResult instanceof Left);
        final Left<Exception, TgVehicle> setError = (Left<Exception, TgVehicle>) setStationResult;
        assertTrue(setError.value instanceof StrictProxyException);
    }

    @Test
    public void ordinary_non_persistent_properties_in_persistent_entities_do_not_get_proxied() {
        try (final Stream<TgVehicleModel> stream = co(TgVehicleModel.class).stream(from(select(TgVehicleModel.class).model()).with(fetchOnly(TgVehicleModel.class).with("key")).model())) {
            stream.forEach(vm -> {
                assertFalse("Oridinary, not persistent props should not be proxied", isPropertyProxied(vm, "ordinaryIntProp"));
                assertNull(vm.getOrdinaryIntProp());
                assertFalse("Fetched inherited @MapTo props should not be proxied.", isPropertyProxied(vm, "key"));
            });
        }
    }

    @Test
    public void properties_of_synthetic_entities_get_proxied_except_crit_only_ones() {
        try (final Stream<TgReVehicleModel> stream = co(TgReVehicleModel.class)
                                                    .stream(from(select(TgReVehicleModel.class).model())
                                                            .with(fetchOnly(TgReVehicleModel.class).with("key")).model())) {
            stream.forEach(vm -> {
                assertTrue("Not-fetched yielded props should be proxied", isPropertyProxied(vm, "intProp"));
                assertTrue("Not-feched and not-yielded props should be proxied", isPropertyProxied(vm, "noYieldIntProp"));
                assertTrue("Not-fetched inherited @MapTo props should be proxied", isPropertyProxied(vm, "make"));
                assertTrue("Even inherited, oridinary, not persistent props should become proxied in the context of a synthetic entity", isPropertyProxied(vm, "ordinaryIntProp"));
                assertFalse("@CritOnly props should not be proxied", isPropertyProxied(vm, "intCritProp"));
                assertFalse("Fetched inherited @MapTo props should not be proxied.", isPropertyProxied(vm, "key"));
                assertNull(vm.getIntCritProp());
            });
        }
    }

    @Test
    public void not_yielded_but_fetched_properties_of_synthetic_entities_do_not_get_proxied() {

        try (final Stream<TgReVehicleModel> stream = co(TgReVehicleModel.class)
                                                    .stream(from(select(TgReVehicleModel.class).model())
                                                            .with(fetchOnly(TgReVehicleModel.class).with("key").with("noYieldIntProp")).model())) {
            stream.forEach(vm -> {
                assertFalse("Feched and not-yielded props should not be proxied", isPropertyProxied(vm, "noYieldIntProp"));
                assertNull(vm.getNoYieldIntProp());
            });
        }
    }

    @Override
    public boolean useSavedDataPopulationScript() {
        return false;
    }

    @Override
    public boolean saveDataPopulationScriptToFile() {
        return false;
    }

    @Override
    protected void populateDomain() {
        if (useSavedDataPopulationScript()) {
            return;
        }

        super.populateDomain();

        final TgFuelType unleadedFuelType = save(new_(TgFuelType.class, "U", "Unleaded"));
        final TgFuelType petrolFuelType = save(new_(TgFuelType.class, "P", "Petrol"));

        final TgWorkshop workshop1 = save(new_(TgWorkshop.class, "WSHOP1", "Workshop 1"));
        final TgWorkshop workshop2 = save(new_(TgWorkshop.class, "WSHOP2", "Workshop 2"));

        final TgBogieLocation location = co$(TgBogieLocation.class).new_();
        location.setWorkshop(workshop1);
        final TgBogie bogie1 = save(new_(TgBogie.class, "BOGIE1", "Bogie 1").setLocation(location));
        final TgBogie bogie2 = save(new_(TgBogie.class, "BOGIE2", "Bogie 2"));
        final TgBogie bogie3 = save(new_(TgBogie.class, "BOGIE3", "Bogie 3"));
        final TgBogie bogie4 = save(new_(TgBogie.class, "BOGIE4", "Bogie 4"));
        final TgBogie bogie5 = save(new_(TgBogie.class, "BOGIE5", "Bogie 5"));
        final TgBogie bogie6 = save(new_(TgBogie.class, "BOGIE6", "Bogie 6"));
        final TgBogie bogie7 = save(new_(TgBogie.class, "BOGIE7", "Bogie 7"));

        final TgWagon wagon1 = save(new_(TgWagon.class, "WAGON1", "Wagon 1"));
        final TgWagon wagon2 = save(new_(TgWagon.class, "WAGON2", "Wagon 2"));

        save(new_composite(TgWagonSlot.class, wagon1, 5));
        save(new_composite(TgWagonSlot.class, wagon1, 6));
        save(new_composite(TgWagonSlot.class, wagon1, 7));
        save(new_composite(TgWagonSlot.class, wagon1, 8));
        save(new_composite(TgWagonSlot.class, wagon1, 4).setBogie(bogie1));
        save(new_composite(TgWagonSlot.class, wagon1, 3).setBogie(bogie2));
        save(new_composite(TgWagonSlot.class, wagon1, 2).setBogie(bogie3));
        save(new_composite(TgWagonSlot.class, wagon1, 1).setBogie(bogie4));

        save(new_composite(TgWagonSlot.class, wagon2, 1).setBogie(bogie5));
        save(new_composite(TgWagonSlot.class, wagon2, 2).setBogie(bogie6));
        save(new_composite(TgWagonSlot.class, wagon2, 3).setBogie(bogie7));

        final TgOrgUnit1 orgUnit1 = save(new_(TgOrgUnit1.class, "orgunit1", "desc orgunit1"));
        final TgOrgUnit2 orgUnit2 = save(new_composite(TgOrgUnit2.class, orgUnit1, "orgunit2"));
        final TgOrgUnit3 orgUnit3 = save(new_composite(TgOrgUnit3.class, orgUnit2, "orgunit3"));
        final TgOrgUnit4 orgUnit4 = save(new_composite(TgOrgUnit4.class, orgUnit3, "orgunit4"));
        final TgOrgUnit5 orgUnit5 = save(new_composite(TgOrgUnit5.class, orgUnit4, "orgunit5"));
        final TgOrgUnit5 orgUnit5_1 = save(new_composite(TgOrgUnit5.class, orgUnit4, "orgunit5_1"));

        final TgVehicleMake merc = save(new_(TgVehicleMake.class, "MERC", "Mercedes"));
        final TgVehicleMake audi = save(new_(TgVehicleMake.class, "AUDI", "Audi"));
        final TgVehicleMake bmw = save(new_(TgVehicleMake.class, "BMW", "BMW"));
        final TgVehicleMake subaro = save(new_(TgVehicleMake.class, "SUBARO", "Subaro"));

        final TgVehicleModel m316 = save(new_(TgVehicleModel.class, "316", "316").setMake(merc));
        final TgVehicleModel m317 = save(new_(TgVehicleModel.class, "317", "317").setMake(audi));
        final TgVehicleModel m318 = save(new_(TgVehicleModel.class, "318", "318").setMake(audi));
        final TgVehicleModel m319 = save(new_(TgVehicleModel.class, "319", "319").setMake(bmw));
        final TgVehicleModel m320 = save(new_(TgVehicleModel.class, "320", "320").setMake(bmw));
        final TgVehicleModel m321 = save(new_(TgVehicleModel.class, "321", "321").setMake(bmw));
        final TgVehicleModel m322 = save(new_(TgVehicleModel.class, "322", "322").setMake(bmw));

        final TgVehicle car1 = save(new_(TgVehicle.class, "CAR1", "CAR1 DESC").setInitDate(date("2001-01-01 00:00:00")).setModel(m318).setPrice(new Money("20")).setPurchasePrice(new Money("10")).setActive(true).setLeased(false));
        final TgVehicle car2 = save(new_(TgVehicle.class, "CAR2", "CAR2 DESC").setInitDate(date("2007-01-01 00:00:00")).setModel(m316).setPrice(new Money("200")).setPurchasePrice(new Money("100")).setActive(false).setLeased(true).setLastMeterReading(new BigDecimal("105")).setStation(orgUnit5).setReplacedBy(car1));

        save(new_(TgVehicleFinDetails.class, car1).setCapitalWorksNo("CAP_NO1"));

        save(new_composite(TgFuelUsage.class, car2, date("2006-02-09 00:00:00")).setQty(new BigDecimal("100")).setFuelType(unleadedFuelType));
        save(new_composite(TgFuelUsage.class, car2, date("2008-02-10 00:00:00")).setQty(new BigDecimal("120")).setFuelType(petrolFuelType));

        save(new_composite(TgTimesheet.class, "USER1", date("2011-11-01 13:00:00")).setFinishDate(date("2011-11-01 15:00:00")).setIncident("002"));

        final UserRole managerRole = save(new_(UserRole.class, "MANAGER", "Managerial role"));
        final UserRole dataEntryRole = save(new_(UserRole.class, "DATAENTRY", "Data entry role"));
        final UserRole analyticRole = save(new_(UserRole.class, "ANALYTIC", "Analytic role"));
        final UserRole fleetOperatorRole = save(new_(UserRole.class, "FLEET_OPERATOR", "Fleet operator role"));
        final UserRole workshopOperatorRole = save(new_(UserRole.class, "WORKSHOP_OPERATOR", "Workshop operator role"));
        final UserRole warehouseOperatorRole = save(new_(UserRole.class, "WAREHOUSE_OPERATOR", "Warehouse operator role"));

        final User baseUser1 = save(new_(User.class, "base_user1", "base user1").setBase(true));
        final User user1 = save(new_(User.class, "user1", "user1 desc").setBase(false).setBasedOnUser(baseUser1)); //.setPassword("password1")
        final User user2 = save(new_(User.class, "user2", "user2 desc").setBase(false).setBasedOnUser(baseUser1));
        final User user3 = save(new_(User.class, "user3", "user3 desc").setBase(false).setBasedOnUser(baseUser1));

        save(new_composite(UserAndRoleAssociation.class, user1, managerRole));
        save(new_composite(UserAndRoleAssociation.class, user1, analyticRole));
        save(new_composite(UserAndRoleAssociation.class, user2, dataEntryRole));
        save(new_composite(UserAndRoleAssociation.class, user2, fleetOperatorRole));
        save(new_composite(UserAndRoleAssociation.class, user2, warehouseOperatorRole));
        save(new_composite(UserAndRoleAssociation.class, user3, dataEntryRole));
        save(new_composite(UserAndRoleAssociation.class, user3, fleetOperatorRole));
        save(new_composite(UserAndRoleAssociation.class, user3, warehouseOperatorRole));

        final TgPersonName chris = save(new_(TgPersonName.class, "Chris", "Chris"));
        save(new_composite(TgAuthor.class, chris, "Date", null));

        final TgPersonName yurij = save(new_(TgPersonName.class, "Yurij", "Yurij"));
        save(new_composite(TgAuthor.class, yurij, "Shcherbyna", "Mykolajovych"));
    }

}


text:
<?php

namespace Horde\GitTools\Action\Dev;

use Horde\GitTools\Cli;

/**
 * Empty the linked directories of a Git install.
 *
 * @author    Michael J Rubinsky <mrubinsk@horde.org>
 * @author    Michael Slusarz <slusarz@horde.org>
 * @category  Horde
 * @copyright 2017 Horde LLC
 * @license   https://www.horde.org/licenses/bsd BSD
 * @package   GitTools
 */
class EmptyLinkedDirectory extends \Horde\GitTools\Action\Base
{
    /**
     */
    public function run()
    {
        $web_dir = rtrim(ltrim($this->_params['web_base']), '/ ');
        $this->_emptyWebDir($web_dir);
    }

    /**
     * Empties the web directory.
     *
     * @param  string $web_dir    Path to the web accessible directory.
     */
    protected function _emptyWebDir($web_dir)
    {
        $this->_dependencies->getOutput()->info("EMPTYING old web directory $web_dir");
        try {
            $it = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($web_dir), \RecursiveIteratorIterator::CHILD_FIRST);
        } catch (\UnexpectedValueException $e) {
            $this->_dependencies->getOutput()->info('Old web directory not found. Creating it.');
            mkdir($web_dir);
            $it = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($web_dir), \RecursiveIteratorIterator::CHILD_FIRST);
        }
        while ($it->valid()) {
            if (!$it->isDot()) {
                if ($it->isLink()) {
                    if ($this->_params['verbose']) {
                        $this->_dependencies->getOutput()->info('DELETING LINK: ' . $it->key());
                    }
                    unlink($it->key());
                } elseif ($it->isDir()) {
                    if ($this->_params['verbose']) {
                        $this->_dependencies->getOutput()->info('DELETING DIR: ' . $it->key());
                    }
                    rmdir($it->key());
                } elseif ($it->isFile()) {
                    if ($this->_params['verbose']) {
                        $this->_dependencies->getOutput()->info('DELETING FILE: ' . $it->key());
                    }
                    unlink($it->key());
                }
            }
            $it->next();
        }
    }

}


text:
The HTTP API
=

The IHttpRequest and IHttpResponse interfaces are exposed as Python classes (both inheriting from IHttpBase)

Unit tests available here: https://github.com/20tab/UnrealEnginePython/blob/master/tests/test_http.py

The usage is pretty 'pythonic' and support both polling and evented approaches:

```python
from unreal_engine import IHttpRequest
import json

request = IHttpRequest('GET', 'http://httpbin.org/user-agent')

def response_received(request, response, success):
    data = json.loads(response.get_content_as_string())
    ue.log(data['user-agent'])

# bind OnProcessRequestComplete event to the response_received callable
request.bind_on_process_request_complete(response_received)

# run the request
request.process_request()
```

If you prefer the polling apparoach, you need to check for the get_status() return value (an int). In the C++ it is defined as:

```c++
namespace EHttpRequestStatus
{
    enum Type
    {
        NotStarted,
        Processing,
        Failed,
        Failed_ConnectionError,
        Succeeded,
    }
}
```

so any value >= 2 will be a sign of request completion:

```python
from unreal_engine import IHttpRequest
import json

request = IHttpRequest('GET', 'http://httpbin.org/user-agent')

# run the request
request.process_request()

# check its status

if request.get_status() >= 2:
    response = request.get_response()
    data = json.loads(response.get_content_as_string())
    ue.log(data['user-agent'])
```

If you want to call request.get_status() in a loop  ensure to 'tick' it (otherwise you will block forever as python will never give back control to unreal):

```python
from unreal_engine import IHttpRequest
import json

request = IHttpRequest('GET', 'http://httpbin.org/user-agent')

# run the request
request.process_request()

# check its status
# tick it at each iteration to avoid blocking ue forever !
# the argument of tick is the DeltaSeconds added to the value returned by get_elapsed_time()
while request.get_status() < 2:
    request.tick(0.01)

response = request.get_response()
data = json.loads(response.get_content_as_string())
ue.log(data['user-agent'])
```

In case of long running requests, another event can be bound:

```python
from unreal_engine import IHttpRequest
import json

request = IHttpRequest('GET', 'http://httpbin.org/user-agent')

def response_received(request, response, success):
    data = json.loads(response.get_content_as_string())
    ue.log(data['user-agent'])

def request_progress(request, sent, received):
    ue.log(sent)
    ue.log(received)

# bind OnProcessRequestComplete event to the response_received callable
request.bind_on_process_request_complete(response_received)

request.bind_on_request_progress(request_progress)

# run the request
request.process_request()
```

Exposed methods for IHttpBase (inherited by IHttpRequest and IHttpResponse)
-

### get_content()

returns the payload of the request/response

### get_all_headers()

returns a the list of headers as a list of string, with each item as 'HeaderKey: HeaderValue'

### get_content_length()

returns the request/response body length

### get_content_type()

returns the request/response body content type

### get_header(name)

returns the value of the specified request/response header

### get_url()

returns the url

### get_url_parameter(name)

get the value of a url query string item

Exposed methods for IHttpRequest
-

### bind_on_process_request_complete(callable)

Assign a python callable to the OnProcessRequestComplete event

### bind_on_request_progress(callable)

Assign a python callable to the OnRequestProcess event

### append_to_header(key, value)

append a new value to an already existent request header

### cancel_request()

cancel a running request

### get_elapsed_time()

get the amount of seconds the request took to complete (governed by tick)

### get_response()

get the IHttpResponse of the request (if available)

### get_status()

get the status of the request (see above for possible values)

### get_verb()

get the http METHOD of the request (if set)

### process_request()

run the request

### set_content(body)

set the request body (as string or bytes)

### set_header(key, value)

set a request header

### set_url(url)

assign the url to the request

### set_verb(http_method)

assign the http METHOD to the request

### tick(delta_seconds)

'tick' the http engine

Exposed methods for IHttpResponse
-

### get_response_code()

returns the response status code

### get_content_as_string()

returns the response body as a string


text:
package edu.northwestern.bioinformatics.studycalendar.security.plugin.cas;

import org.acegisecurity.AuthenticationException;
import org.acegisecurity.ui.cas.CasProcessingFilterEntryPoint;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * This class wraps {@link CasProcessingFilterEntryPoint} to prevent it from asking the container to
 * append JSESSIONID to the service URL.  This behavior is configurable in Spring Security 2 so
 * we should be able to remove this class when we upgrade.
 *
 * @see http://jira.springframework.org/browse/SEC-306
 * @author Rhett Sutphin
 */
public class NoJsessionidEntryPoint extends CasProcessingFilterEntryPoint {
    @Override
    public void commence(
        ServletRequest servletRequest, ServletResponse servletResponse, AuthenticationException e
    ) throws IOException, ServletException {
        super.commence(servletRequest, wrap((HttpServletResponse) servletResponse), e);
    }

    private ServletResponse wrap(HttpServletResponse originalResponse) {
        return (ServletResponse) Proxy.newProxyInstance(
            originalResponse.getClass().getClassLoader(),
            new Class[] { HttpServletResponse.class },
            new NoEncodeHandler(originalResponse));
    }

    private class NoEncodeHandler implements InvocationHandler {
        private HttpServletResponse originalResponse;

        public NoEncodeHandler(HttpServletResponse originalResponse) {
            this.originalResponse = originalResponse;
        }

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if ("encodeURL".equals(method.getName()) && args.length == 1) {
                return args[0];
            } else {
                return method.invoke(originalResponse, args);
            }
        }
    }
}


text:
package org.motechproject.mds.it.osgi;

import org.apache.commons.beanutils.MethodUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
import org.joda.time.Period;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.motechproject.commons.api.Range;
import org.motechproject.commons.date.model.Time;
import org.motechproject.commons.date.util.DateUtil;
import org.motechproject.commons.sql.service.SqlDBManager;
import org.motechproject.config.core.constants.ConfigurationConstants;
import org.motechproject.config.core.service.CoreConfigurationService;
import org.motechproject.mds.domain.Field;
import org.motechproject.mds.dto.CsvImportResults;
import org.motechproject.mds.dto.DraftData;
import org.motechproject.mds.dto.DtoHelper;
import org.motechproject.mds.dto.EntityDto;
import org.motechproject.mds.dto.FieldBasicDto;
import org.motechproject.mds.dto.FieldDto;
import org.motechproject.mds.dto.LookupDto;
import org.motechproject.mds.dto.LookupFieldDto;
import org.motechproject.mds.dto.LookupFieldType;
import org.motechproject.mds.dto.MetadataDto;
import org.motechproject.mds.dto.SettingDto;
import org.motechproject.mds.dto.TypeDto;
import org.motechproject.mds.osgi.TestClass;
import org.motechproject.mds.query.QueryExecution;
import org.motechproject.mds.query.QueryExecutor;
import org.motechproject.mds.query.QueryParams;
import org.motechproject.mds.query.SqlQueryExecution;
import org.motechproject.mds.service.ComboboxValueService;
import org.motechproject.mds.service.CsvImportExportService;
import org.motechproject.mds.service.EntityService;
import org.motechproject.mds.service.JarGeneratorService;
import org.motechproject.mds.service.MDSLookupService;
import org.motechproject.mds.service.MetadataService;
import org.motechproject.mds.service.MotechDataService;
import org.motechproject.mds.service.RestDocumentationService;
import org.motechproject.mds.testutil.DraftBuilder;
import org.motechproject.mds.util.ClassName;
import org.motechproject.mds.util.Constants;
import org.motechproject.mds.util.InstanceSecurityRestriction;
import org.motechproject.mds.util.Order;
import org.motechproject.mds.util.PropertyUtil;
import org.motechproject.testing.osgi.BasePaxIT;
import org.motechproject.testing.osgi.container.MotechNativeTestContainerFactory;
import org.motechproject.testing.osgi.helper.ServiceRetriever;
import org.ops4j.pax.exam.ExamFactory;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
import org.ops4j.pax.exam.spi.reactors.PerSuite;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.context.WebApplicationContext;

import javax.inject.Inject;
import javax.jdo.Query;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.motechproject.mds.dto.SettingOptions.REQUIRE;
import static org.motechproject.mds.dto.TypeDto.BOOLEAN;
import static org.motechproject.mds.dto.TypeDto.COLLECTION;
import static org.motechproject.mds.util.Constants.BundleNames.MDS_BUNDLE_SYMBOLIC_NAME;
import static org.motechproject.mds.util.Constants.BundleNames.MDS_ENTITIES_SYMBOLIC_NAME;
import static org.motechproject.mds.util.Constants.MetadataKeys.MAP_KEY_TYPE;
import static org.motechproject.mds.util.Constants.MetadataKeys.MAP_VALUE_TYPE;

@RunWith(PaxExam.class)
@ExamReactorStrategy(PerSuite.class)
@ExamFactory(MotechNativeTestContainerFactory.class)
public class MdsBundleIT extends BasePaxIT {

    private static final String FOO = "Foo";
    private static final String FOO_CLASS = String.format("%s.%s", Constants.PackagesGenerated.ENTITY, FOO);

    private static final int INSTANCE_COUNT = 5;
    private static final Byte[] BYTE_ARRAY_VALUE = new Byte[]{110, 111, 112};
    private static final Period TEST_PERIOD = new Period().withDays(3).withHours(7).withMinutes(50);
    private static final Period NEW_PERIOD = new Period().withYears(2).withMinutes(10);
    private static final Map<String, TestClass> TEST_MAP = new HashMap<>();
    private static final Map<String, TestClass> TEST_MAP2 = new HashMap<>();
    private static final DateTime NOW = DateUtil.now().secondOfMinute().roundFloorCopy();
    private static final LocalDateTime JAVA_NOW = LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES);
    private static final DateTime YEAR_LATER = NOW.plusYears(1);
    private static final LocalDate LD_NOW = NOW.toLocalDate();
    private static final java.time.LocalDate JAVA_LD_NOW = JAVA_NOW.toLocalDate();
    private static final LocalDate LD_YEAR_AGO = LD_NOW.minusYears(1);
    private static final Date DATE_NOW = NOW.toDate();
    private static final Date DATE_TOMORROW = NOW.plusDays(1).toDate();
    private static final Double DOUBLE_VALUE_1 = 4.725;
    private static final Double DOUBLE_VALUE_2 = 3.14;
    private static final Time MORNING_TIME = new Time(8, 15);
    private static final Time NIGHT_TIME = new Time(23, 4);

    static {
        TEST_MAP.put("key1", new TestClass(123, "abc"));
        TEST_MAP.put("key2", new TestClass(456, "ddd"));

        TEST_MAP2.put("key4", new TestClass(4, "ads"));
        TEST_MAP2.put("key3", new TestClass(21, "test"));
    }

    private JarGeneratorService generator;
    private EntityService entityService;
    private MotechDataService service;
    private File configurationFile;
    private String startingCacheType;

    @Inject
    private SqlDBManager sqlDBManager;

    @Inject
    private BundleContext bundleContext;

    @Inject
    private MDSLookupService mdsLookupService;

    @Inject
    private RestDocumentationService restDocService;

    @Inject
    private CoreConfigurationService coreConfigurationService;

    @Before
    public void setUp() throws Exception {
        WebApplicationContext context = ServiceRetriever.getWebAppContext(bundleContext, MDS_BUNDLE_SYMBOLIC_NAME, 10000, 12);

        entityService = context.getBean(EntityService.class);
        generator = context.getBean(JarGeneratorService.class);

        clearEntities();
        setUpSecurityContextForDefaultUser("mdsSchemaAccess");

        //Prepare file with datanucleus configuration for later use to
        //turn off and on l2 cache
        configurationFile = new File(coreConfigurationService.getConfigLocation().getLocation()
                .concat("/" + ConfigurationConstants.DATANUCLEUS_SETTINGS_FILE_NAME));
        //Remember starting cache type. It will be restored after tests
        startingCacheType = coreConfigurationService.loadDatanucleusConfig().getProperty("datanucleus.cache.level2.type");
    }

    @After
    public void tearDown() throws Exception {
        clearEntities();
        setCacheType(startingCacheType);
    }

    @Test
    public void testEntitiesBundleInstallsProperly() throws Exception {

        //Run tests with l2 cache active
        testEntitiesBundleInstallsProperly(true);

        //Run tests without l2 cache
        setCacheType("none");
        testEntitiesBundleInstallsProperly(false);
    }

    private void testEntitiesBundleInstallsProperly(boolean withCache) throws Exception {
        final String serviceName = ClassName.getInterfaceName(FOO_CLASS);

        //Some additional preparation needed for second run without l2 cache
        if(!withCache) {
            clearEntities();
            generator.regenerateMdsDataBundle();
        }

        prepareTestEntities();

        Bundle entitiesBundle = OsgiBundleUtils.findBundleBySymbolicName(bundleContext, MDS_ENTITIES_SYMBOLIC_NAME);
        assertNotNull(entitiesBundle);

        service = (MotechDataService) ServiceRetriever.getService(bundleContext, serviceName, true);

        Class<?> objectClass = entitiesBundle.loadClass(FOO_CLASS);
        getLogger().info("Loaded class: " + objectClass.getName());

        clearInstances();

        verifyMetadataRetrieval();
        verifyInstanceCreatingAndRetrieving(objectClass);
        verifyInstanceCreatingOrUpdating(objectClass);
        verifyLookups(false); // regular lookups
        verifyLookups(true); // using the lookup service
        verifyComboboxValueUpdate();
        verifyInstanceUpdating();
        verifyCustomQuery();
        verifyCsvImport();
        verifyCsvImportIsOneTransaction();
        verifyColumnNameChange();
        verifyComboboxDataMigration();
        verifyInstanceDeleting();
        verifyRestDocumentation();
    }

    private void verifyComboboxDataMigration() throws NoSuchFieldException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        Long entityId = entityService.getEntityByClassName(FOO_CLASS).getId();
        Long fieldId = getFieldIdByName(entityService.getFields(entityId), "someEnum");

        DraftData draft = DraftBuilder.forFieldEdit(fieldId, "settings.2.value", true);

        entityService.saveDraftEntityChanges(entityId, draft);
        entityService.commitChanges(entityId);

        generator.regenerateMdsDataBundle(true);
        service = (MotechDataService) ServiceRetriever.getService(bundleContext, ClassName.getInterfaceName(FOO_CLASS), true);

        assertValuesEqual(getExpectedComboboxValues(), getValues(service.retrieveAll()));
    }

    private void assertValuesEqual(List<List<Object>> expected, List<List<Object>> result) {
        boolean equal = true;

        for (int i = 0; i < expected.size(); i++) {
            if (!expected.get(i).isEmpty()) {
                if (!expected.get(i).get(0).toString().equals(result.get(i).get(0).toString())) {
                    equal = false;
                    break;
                }
            } else {
                if (!result.get(i).isEmpty()) {
                    equal = false;
                    break;
                }
            }
        }

        assertTrue(equal);
    }

    private List<List<Object>> getExpectedComboboxValues() throws ClassNotFoundException, NoSuchFieldException {
        Class aClass = OsgiBundleUtils.findBundleBySymbolicName(bundleContext, MDS_ENTITIES_SYMBOLIC_NAME).loadClass(FOO_CLASS);
        List<List<Object>> values = new ArrayList<>();

        List<Object> value = new ArrayList<>();
        value.add(toEnum(aClass, "two"));
        values.add(value);
        values.add(value);

        value = new ArrayList<>();
        value.add(toEnum(aClass, "three"));
        values.add(value);

        value = new ArrayList<>();
        value.add(toEnum(aClass, "one"));
        values.add(value);

        value = new ArrayList<>();
        value.add(toEnum(aClass, "two"));
        values.add(value);

        value = new ArrayList<>();
        values.add(value);
        values.add(value);

        return values;
    }

    private List<List<Object>> getValues(List instances) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        List<List<Object>> values = new ArrayList<>();
        for (Object instance : instances) {

            values.add((List<Object>)instance.getClass().getMethod("getSomeEnum").invoke(instance));
        }
        return values;
    }

    private Long getFieldIdByName(List<FieldDto> fields, String name) {
        Long fieldId = null;

        for (FieldDto field : fields) {
            if(field.getBasic().getName().equals(name)) {
                fieldId = field.getId();
                break;
            }
        }

        return  fieldId;
    }

    private void clearInstances() {
        service.deleteAll();
    }

    private void verifyInstanceCreatingAndRetrieving(Class<?> loadedClass) throws Exception {
        getLogger().info("Verifying instance creation and retrieval");

        Object instance = loadedClass.newInstance();
        Object instance2 = loadedClass.newInstance();
        Object instance3 = loadedClass.newInstance();
        Object instance4 = loadedClass.newInstance();
        Object instance5 = loadedClass.newInstance();

        // instance 1
        updateInstance(instance, true, "trueNow", "trueNowCp", new ArrayList(asList("1", "2", "3")),
                       NOW, LD_NOW, TEST_MAP, TEST_PERIOD, BYTE_ARRAY_VALUE,
                       DATE_NOW, DOUBLE_VALUE_1, MORNING_TIME, 1, toEnum(loadedClass, "one"),
                       JAVA_LD_NOW, JAVA_NOW);

        // instance 2
        updateInstance(instance2, true, "trueInRange", "trueInRangeCp", new ArrayList(asList("2", "4")),
                       NOW.plusHours(1), LD_NOW.plusDays(1), TEST_MAP, TEST_PERIOD, BYTE_ARRAY_VALUE,
                       DATE_NOW, DOUBLE_VALUE_1, MORNING_TIME, 2, toEnum(loadedClass, "two"),
                       JAVA_LD_NOW.plusDays(1), JAVA_NOW.plusHours(1));

        // instance 3
        updateInstance(instance3, false, "falseInRange", "falseInRangeCp", null,
                       NOW.plusHours(2), LD_NOW.plusDays(1), null, TEST_PERIOD, BYTE_ARRAY_VALUE,
                       DATE_TOMORROW, DOUBLE_VALUE_2, NIGHT_TIME, 2, toEnum(loadedClass, "three"),
                       JAVA_LD_NOW.plusDays(2), JAVA_NOW.plusHours(2));

        // instance 4
        updateInstance(instance4, true, "trueOutOfRange", "trueOutOfRangeCp", null,
                       NOW.plusHours(3), LD_NOW.plusDays(10), null, TEST_PERIOD, BYTE_ARRAY_VALUE,
                       DATE_TOMORROW, DOUBLE_VALUE_2, NIGHT_TIME, 3, toEnum(loadedClass, "one"),
                       JAVA_LD_NOW.plusDays(3), JAVA_NOW.plusHours(3));

        // instance 5
        updateInstance(instance5, true, "notInSet", "notInSetCp", null,
                       NOW.plusHours(4), LD_NOW, null, TEST_PERIOD, BYTE_ARRAY_VALUE,
                       DATE_NOW, DOUBLE_VALUE_2, MORNING_TIME, 4, toEnum(loadedClass, "two"),
                       JAVA_LD_NOW.plusDays(4), JAVA_NOW.plusHours(4));

        //Single object return lookup should return 0 if there are no instances
        Long emptyCount = (Long) MethodUtils.invokeMethod(service, "countByUniqueString", "trueNow");
        assertEquals(emptyCount, (Long) 0L);

        service.create(instance);
        Object retrieved = service.retrieveAll(QueryParams.ascOrder("someDateTime")).get(0);

        //Single object return lookup should return 1 if there is instance with unique value in field
        Long count = (Long) MethodUtils.invokeMethod(service, "countByUniqueString", "trueNow");
        assertEquals(count, (Long) 1L);

        assertInstanceOne(retrieved, loadedClass);

        assertEquals(1, service.retrieveAll().size());
        service.create(instance2);
        service.create(instance3);
        service.create(instance4);
        service.create(instance5);
        assertEquals(INSTANCE_COUNT, service.retrieveAll().size());

        // verify double order
        QueryParams queryParams = new QueryParams(asList(new Order("someLocalDate", Order.Direction.DESC),
                new Order("someString", Order.Direction.ASC)));
        List<Object> result = service.retrieveAll(queryParams);

        assertNotNull(result);
        assertEquals(5, result.size());
        assertInstanceFour(result.get(0), loadedClass);
        assertInstanceThree(result.get(1), loadedClass);
        assertInstanceTwo(result.get(2), loadedClass);
        assertInstanceFive(result.get(3), loadedClass);
        assertInstanceOne(result.get(4), loadedClass);
    }

    private void verifyLookups(boolean usingLookupService) throws Exception{
        // if using lookup service set tot true then all data access
        // is done through the MdsLookupService
        // otherwise we call the methods on the data service

        if (usingLookupService) {
            getLogger().info("Verifying lookups using lookup service");
        } else {
            getLogger().info("Verifying lookups");
        }

        Object resultObj = (usingLookupService) ?
                mdsLookupService.retrieveAll(FOO_CLASS, QueryParams.ascOrder("someDateTime")) :
                service.retrieveAll(QueryParams.ascOrder("someDateTime"));

        assertTrue(resultObj instanceof List);
        List resultList = (List) resultObj;
        assertEquals(5, resultList.size());

        Class objClass = resultList.get(0).getClass();

        assertInstanceOne(resultList.get(0), objClass);

        // verify lookups
        if (usingLookupService) {
            Map<String, Boolean> lookupMap = new HashMap<>();
            lookupMap.put("someBoolean", true);
            resultObj = mdsLookupService.findMany(FOO_CLASS, "By boolean",
                    lookupMap, QueryParams.ascOrder("someDateTime"));
        } else {
            resultObj = MethodUtils.invokeMethod(service, "byBool",
                    new Object[]{true, QueryParams.ascOrder("someDateTime")});
        }

        assertTrue(resultObj instanceof List);
        resultList = (List) resultObj;

        assertEquals(4, resultList.size());
        assertInstanceOne(resultList.get(0), objClass);

        List<String> list = new ArrayList<>();
        list.add("2");
        Range<DateTime> range = new Range<>(NOW.minusHours(1), NOW.plusHours(5));
        Set<String> set = new HashSet<>(asList("trueNow", "trueInRange", "trueOutOfRange", "falseInRange"));

        // only two instances should match this criteria
        if (usingLookupService) {
            Map<String, Object> lookupMap = new HashMap<>();
            lookupMap.put("someBoolean", true);
            lookupMap.put("someDateTime", range);
            lookupMap.put("someString", set);
            lookupMap.put("someList", list);

            resultObj = mdsLookupService.findMany(FOO_CLASS, "Combined", lookupMap, QueryParams.descOrder("someDateTime"));
        } else {
            resultObj = MethodUtils.invokeMethod(service, "combined",
                    new Object[]{true, range, set, list, QueryParams.descOrder("someDateTime")});
        }

        assertTrue(resultObj instanceof List);
        resultList = (List) resultObj;
        assertEquals(2, resultList.size());
        assertInstanceTwo(resultList.get(0), objClass);
        assertInstanceOne(resultList.get(1), objClass);

        // usage of a custom operator
        if (usingLookupService) {
            Map<String, Integer> lookupMap = new HashMap<>();
            lookupMap.put("someInt", 2);
            resultObj = mdsLookupService.findMany(FOO_CLASS, "With custom operator", lookupMap,
                    QueryParams.ascOrder("someDateTime"));
        } else {
            resultObj = MethodUtils.invokeMethod(service, "customOperator",
                    new Object[]{2, QueryParams.ascOrder("someDateTime")});
        }

        assertTrue(resultObj instanceof List);
        resultList = (List) resultObj;
        assertEquals(3, resultList.size());
        assertInstanceOne(resultList.get(0), objClass);
        assertInstanceTwo(resultList.get(1), objClass);
        assertInstanceThree(resultList.get(2), objClass);

        // usage of matches, case sensitive and case insensitive
        String[] textsToSearch = { "true", "TRUE" };
        String[] methodNames = {"matchesOperator", "matchesOperatorCI"};
        String[] lookupNames = {"With matches", "With matches case insensitive"};

        for (int i = 0; i < 2; i++) {
            String textToSearch = textsToSearch[i];
            String methodName = methodNames[i];
            String lookupName = lookupNames[i];

            if (usingLookupService) {
                Map<String, String> lookupMap = new HashMap<>();
                lookupMap.put("someString", textToSearch);
                resultObj = mdsLookupService.findMany(FOO_CLASS, lookupName, lookupMap, QueryParams.ascOrder("someDateTime"));
            } else {
                resultObj = MethodUtils.invokeMethod(service, methodName,
                        new Object[]{textToSearch, QueryParams.ascOrder("someDateTime")});
            }

            assertTrue(resultObj instanceof List);
            resultList = (List) resultObj;
            assertEquals(3, resultList.size());
            assertInstanceOne(resultList.get(0), objClass);
            assertInstanceTwo(resultList.get(1), objClass);
            assertInstanceFour(resultList.get(2), objClass);
        }
    }

    private void verifyInstanceUpdating() throws Exception {
        getLogger().info("Verifying instance updating");

        List<Object> allObjects = service.retrieveAll(QueryParams.descOrder("someDateTime"));
        assertEquals(allObjects.size(), INSTANCE_COUNT);

        Object retrieved = allObjects.get(0);
        Class objClass = retrieved.getClass();

        // instance 1.1
        updateInstance(retrieved, false, "anotherString", "anotherStringCp", new ArrayList(asList("4", "5")),
                YEAR_LATER, LD_YEAR_AGO, TEST_MAP2, NEW_PERIOD, BYTE_ARRAY_VALUE,
                DATE_TOMORROW, DOUBLE_VALUE_2, NIGHT_TIME, 10, toEnum(objClass, "two"),
                JAVA_LD_NOW.plusDays(5), JAVA_NOW.plusHours(5));

        service.update(retrieved);
        Object updated = service.retrieveAll(QueryParams.descOrder("someDateTime")).get(0);

        assertInstanceOneDotOne(updated, objClass);
    }

    private void verifyInstanceCreatingOrUpdating(Class<?> loadedClass) throws Exception {
        getLogger().info("Verifying instance creating or updating using createOrUpdate() method");

        // Creating a new object using createOrUpdate() method and checking if it was really added
        Object instance = loadedClass.newInstance();

        updateInstance(instance, false, "newInstance", "newInstance", new ArrayList(asList("1", "2", "3")),
                NOW, LD_NOW, TEST_MAP, TEST_PERIOD, BYTE_ARRAY_VALUE,
                DATE_NOW, DOUBLE_VALUE_1, MORNING_TIME, 1, toEnum(loadedClass, "one"),
                JAVA_LD_NOW.plusDays(6), JAVA_NOW.plusHours(6));

        service.createOrUpdate(instance);                           // using createOrUpdate() to create

        List<Object> allObjects = service.retrieveAll();
        assertEquals(allObjects.size(), INSTANCE_COUNT + 1);        // should return one extra object

        // Now update that object using createOrUpdate method and check if it is really updated
        Object retrieved = allObjects.get(INSTANCE_COUNT);          // gets the last added object
        Class objClass = retrieved.getClass();

        updateInstance(retrieved, false, "yetAnotherString", "yetAnotherStringCp", new ArrayList(asList("1", "2", "3")),
                YEAR_LATER, LD_YEAR_AGO, TEST_MAP2, NEW_PERIOD, BYTE_ARRAY_VALUE,
                DATE_TOMORROW, DOUBLE_VALUE_2, NIGHT_TIME, 10, toEnum(objClass, "two"),
                JAVA_LD_NOW.plusDays(7), JAVA_NOW.plusHours(7));

        service.createOrUpdate(retrieved);                          // using createOrUpdate() to update

        assertEquals(allObjects.size(), INSTANCE_COUNT + 1);        // number of objects shouldn't change since last check

        Object updated = service.retrieveAll().get(INSTANCE_COUNT); // gets the last added object

        assertInstance(updated, false, "yetAnotherString", "yetAnotherStringCp", asList("1", "2", "3"),
                YEAR_LATER, LD_YEAR_AGO, TEST_MAP2, NEW_PERIOD, BYTE_ARRAY_VALUE,
                DATE_TOMORROW, DOUBLE_VALUE_2, NIGHT_TIME, 10, toEnum(objClass, "two"),
                JAVA_LD_NOW.plusDays(7), JAVA_NOW.plusHours(7));

        // Remove new object for the sake of other tests
        service.delete(updated);
        allObjects = service.retrieveAll();
        assertEquals(allObjects.size(), INSTANCE_COUNT);            // check if the object is removed
    }

    private void verifyColumnNameChange() throws ClassNotFoundException, InterruptedException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        getLogger().info("Verifying column name change");

        Long entityId = entityService.getEntityByClassName(FOO_CLASS).getId();
        List<Field> fields = entityService.getEntityDraft(entityId).getFields();

        Field fieldToUpdate  = findFieldByName(fields, "someString");

        entityService.saveDraftEntityChanges(entityId, DraftBuilder.forFieldEdit(fieldToUpdate.getId(), "basic.name", "newFieldName"));
        entityService.commitChanges(entityId);

        generator.regenerateMdsDataBundle();

        FieldDto fieldToUpdateDto = DtoHelper.findByName(entityService.getEntityFields(entityId), "newFieldName");

        assertNotNull("Unable to find field named 'newFieldName'", fieldToUpdate);
        assertEquals(String.class.getName(), fieldToUpdateDto.getType().getTypeClass());

        service = (MotechDataService) ServiceRetriever.getService(bundleContext, ClassName.getInterfaceName(FOO_CLASS), true);
        Object retrieved = service.retrieveAll(QueryParams.ascOrder("someDateTime")).get(0);

        Object fieldValue = MethodUtils.invokeMethod(retrieved, "getNewFieldName", null);
        assertNotNull(fieldValue);

        entityId = entityService.getEntityByClassName(FOO_CLASS).getId();
        fields = entityService.getEntityDraft(entityId).getFields();

        fieldToUpdate = findFieldByName(fields, "newFieldName");

        entityService.saveDraftEntityChanges(entityId, DraftBuilder.forFieldEdit(fieldToUpdate.getId(), "basic.name", "someString"));
        entityService.commitChanges(entityId);
        generator.regenerateMdsDataBundle();

        service = (MotechDataService) ServiceRetriever.getService(bundleContext, ClassName.getInterfaceName(FOO_CLASS), true);
    }

    private void verifyCustomQuery() throws Exception {
        List result = (List) service.executeQuery(new QueryExecution<List>() {
            @Override
            public List execute(Query query, InstanceSecurityRestriction restriction) {
                query.setFilter("someString == param0");
                query.declareParameters("java.lang.String param0");
                return (List) QueryExecutor.execute(query, "anotherString", restriction);
            }
        });
        assertEquals(1, result.size());

        Class objClass = result.get(0).getClass();
        assertInstanceOneDotOne(result.get(0), objClass);

        List<String> names = (List<String>) service.executeSQLQuery(new SqlQueryExecution<List<String>>() {
            @Override
            public List<String> execute(Query query) {
                Map<String, Integer> params = new HashMap<>();
                params.put("param", 4);
                return (List<String>) query.executeWithMap(params);
            }

            @Override
            public String getSqlQuery() {
                String driverName = sqlDBManager.getChosenSQLDriver();
                if (driverName.equals(Constants.Config.MYSQL_DRIVER_CLASSNAME)) {
                    return "SELECT someString FROM MDS_FOO WHERE someInt = :param";
                } else {
                    return "SELECT \"someString\" FROM \"MDS_FOO\" WHERE \"someInt\" = :param";
                }
            }
        });
        assertEquals(asList("notInSet"), names);
    }

    private void verifyInstanceDeleting() throws IllegalAccessException, InstantiationException {
        getLogger().info("Verifying instance deleting");

        // 2 instances come from csv
        int instanceCount = INSTANCE_COUNT + 2;

        List<Object> objects = service.retrieveAll();

        for (int i = 0; i < instanceCount; i++) {
            service.delete(objects.get(i));
            assertEquals(instanceCount - i - 1, service.retrieveAll().size());
        }
    }

    private void verifyComboboxValueUpdate() throws Exception {
        getLogger().info("Verifying combobox value update");
        Long entityId = entityService.getEntityByClassName(FOO_CLASS).getId();

        List<Object> allObjects = service.retrieveAll(QueryParams.ascOrder("someDateTime"));
        assertEquals(allObjects.size(), INSTANCE_COUNT);
        Object retrieved = allObjects.get(0);
        Class objClass = retrieved.getClass();

        updateInstance(retrieved, false, "anotherString", "anotherStringCp", new ArrayList(asList("0", "35")),
                YEAR_LATER, LD_YEAR_AGO, TEST_MAP2, NEW_PERIOD, BYTE_ARRAY_VALUE,
                DATE_TOMORROW, DOUBLE_VALUE_2, NIGHT_TIME, 3, toEnum(objClass, "two"),
                JAVA_LD_NOW.minusDays(1), JAVA_NOW.minusHours(1));
        service.update(retrieved);

        ComboboxValueService cbValueService = ServiceRetriever.getService(bundleContext, ComboboxValueService.class);

        assertEquals(asList("0", "2", "35", "4"), cbValueService.getAllValuesForCombobox(FOO_CLASS, "someList"));
    }

    private void verifyCsvImport() throws Exception {
        getLogger().info("Verifying CSV Import");

        CsvImportExportService csvImportExportService = ServiceRetriever.getService(bundleContext, CsvImportExportService.class);

        try (InputStream in = new ClassPathResource("csv/import.csv").getInputStream()) {
            Reader reader = new InputStreamReader(in);
            CsvImportResults results = csvImportExportService.importCsv(FOO_CLASS, reader, "import.csv", false);
            assertNotNull(results);
            assertEquals(2, results.totalNumberOfImportedInstances());
            assertEquals(2, results.newInstanceCount());
            assertEquals(0, results.updatedInstanceCount());
        }

        assertEquals(7, service.count());

        // get the imported instances through a lookup
        QueryParams queryParams = new QueryParams(new Order("someTime", Order.Direction.DESC));
        List list = (List) MethodUtils.invokeExactMethod(service, "matchesOperator",
                new Object[] {"fromCsv", queryParams});

        assertNotNull(list);
        assertEquals(2, list.size());
        assertInstance(list.get(0), false, "fromCsv", "Capital CSV", Collections.emptyList(), null, new LocalDate(2012, 10, 14),
                null, new Period(2, 0, 0, 0, 0, 0, 0, 0), null, new DateTime(2014, 12, 2, 16, 13, 40, 0, DateTimeZone.UTC).toDate(),
                null, new Time(20, 20), null, null, null, null);
        assertInstance(list.get(1), true, "fromCsv", "Capital CSV", new ArrayList(asList("one", "two")),
                new DateTime(2014, 12, 2, 13, 10, 40, 0, DateTimeZone.UTC).withZone(DateTimeZone.getDefault()),
                new LocalDate(2012, 10, 15), null, new Period(1, 0, 0, 0, 0, 0, 0, 0), null,
                new DateTime(2014, 12, 2, 13, 13, 40, 0, DateTimeZone.UTC).toDate(), null, new Time(10, 30),
                null, null, null, null);
    }

    private void verifyCsvImportIsOneTransaction() throws Exception {
        getLogger().info("Verifying that CSV Import is done in one transaction");

        CsvImportExportService csvImportExportService = ServiceRetriever.getService(bundleContext, CsvImportExportService.class);

        boolean exceptionThrown = false;
        try (InputStream in = new ClassPathResource("csv/import.csv").getInputStream()) {
            String csv = IOUtils.toString(in);
            csv += "invalid row";
            csvImportExportService.importCsv(FOO_CLASS, new StringReader(csv), "import.csv", false);
        } catch (RuntimeException e) {
            exceptionThrown = true;
        }

        assertTrue("No exception thrown during invalid CSV import", exceptionThrown);

        // verify that there are no new instances
        assertEquals(7, service.count());
    }

    private void verifyRestDocumentation() {
        StringWriter writer = new StringWriter();
        restDocService.retrieveDocumentation(writer, "/motech-platform-server", new Locale("en", "US"));
        String docs = writer.toString();

        // Verification of generation in done in SwaggerGeneratorTest
        // Here we just check if generation took place. We don't want to export swagger packages.

        assertNotNull(docs);
        assertNotSame("", docs);
    }

    private void verifyMetadataRetrieval() {
        MetadataService metadataService = ServiceRetriever.getService(bundleContext, MetadataService.class);
        assertEquals("MDS_FOO_SOMELIST", metadataService.getComboboxTableName(FOO_CLASS, "someList"));
    }

    private void prepareTestEntities() throws IOException {
        getLogger().info("Preparing entities for testing");

        EntityDto entityDto = new EntityDto(9999L, FOO);
        entityDto = entityService.createEntity(entityDto);
        generator.regenerateMdsDataBundle();

        List<FieldDto> fields = new ArrayList<>();
        fields.add(new FieldDto(null, entityDto.getId(),
                TypeDto.BOOLEAN,
                new FieldBasicDto("Some Boolean", "someBoolean"),
                false, null));
        fields.add(new FieldDto(null, entityDto.getId(),
                TypeDto.STRING,
                new FieldBasicDto("Some String", "someString"),
                false, null, null,
                asList(
                        new SettingDto("mds.form.label.textarea", false, BOOLEAN)
                ), null));
        // test with capitalized name
        fields.add(new FieldDto(null, entityDto.getId(),
                TypeDto.STRING,
                new FieldBasicDto("Capital Name", "CapitalName"),
                false, null, null,
                asList(
                        new SettingDto("mds.form.label.textarea", false, BOOLEAN)
                ), null));
        fields.add(new FieldDto(null, entityDto.getId(),
                COLLECTION,
                new FieldBasicDto("Some List", "someList"),
                false, null, null,
                asList(
                        new SettingDto(Constants.Settings.COMBOBOX_VALUES, new LinkedList<>(), COLLECTION, REQUIRE),
                        new SettingDto(Constants.Settings.ALLOW_USER_SUPPLIED, true, BOOLEAN),
                        new SettingDto(Constants.Settings.ALLOW_MULTIPLE_SELECTIONS, true, BOOLEAN)
                ), null));
        fields.add(new FieldDto(null, entityDto.getId(),
                TypeDto.DATETIME,
                new FieldBasicDto("dateTime", "someDateTime"),
                false, null));
        fields.add(new FieldDto(null, entityDto.getId(),
                TypeDto.DATETIME8,
                new FieldBasicDto("someJavaDateTime", "someJavaDateTime"),
                false, null));
        fields.add(new FieldDto(null, entityDto.getId(),
                TypeDto.MAP,
                new FieldBasicDto("someMap", "someMap"),
                false, Arrays.asList(
                        new MetadataDto(MAP_KEY_TYPE, String.class.getName()),
                        new MetadataDto(MAP_VALUE_TYPE, TestClass.class.getName())),
                null, null,null));
        fields.add(new FieldDto(null, entityDto.getId(),
                TypeDto.PERIOD,
                new FieldBasicDto("somePeriod", "somePeriod"),
                false, null));
        fields.add(new FieldDto(null, entityDto.getId(),
                TypeDto.BLOB,
                new FieldBasicDto("someBlob", "someBlob"),
                false, null));
        fields.add(new FieldDto(null, entityDto.getId(),
                TypeDto.LOCAL_DATE,
                new FieldBasicDto("someLocalDate", "someLocalDate"),
                false, null));
        fields.add(new FieldDto(null, entityDto.getId(),
                TypeDto.LOCAL_DATE8,
                new FieldBasicDto("someJavaDate", "someJavaDate"),
                false, null));
        fields.add(new FieldDto(null, entityDto.getId(),
                TypeDto.DATE,
                new FieldBasicDto("someDate", "someDate"),
                false, null));
        fields.add(new FieldDto(null, entityDto.getId(),
                TypeDto.TIME,
                new FieldBasicDto("someTime", "someTime"),
                false, null));

        List<SettingDto> decimalSettings = asList(new SettingDto("mds.form.label.precision", 10),
                new SettingDto("mds.form.label.scale", 5));

        fields.add(new FieldDto(null, entityDto.getId(),
                TypeDto.DOUBLE,
                new FieldBasicDto("Some Decimal", "someDecimal"),
                false, null, null, decimalSettings, null));

        fields.add(new FieldDto(null, entityDto.getId(),
                TypeDto.INTEGER,
                new FieldBasicDto("someInteger", "someInt"),
                false, null));

        fields.add(new FieldDto(null, entityDto.getId(),
                TypeDto.COLLECTION,
                new FieldBasicDto("Some Enum", "someEnum"),
                false, null, null,
                asList(
                        new SettingDto(Constants.Settings.COMBOBOX_VALUES, asList("one", "two", "three"), COLLECTION, REQUIRE),
                        new SettingDto(Constants.Settings.ALLOW_USER_SUPPLIED, false, BOOLEAN),
                        new SettingDto(Constants.Settings.ALLOW_MULTIPLE_SELECTIONS, false, BOOLEAN)
                ), null));

        entityService.addFields(entityDto, fields);

        List<LookupDto> lookups = new ArrayList<>();
        List<LookupFieldDto> lookupFields = new ArrayList<>();

        lookupFields.add(new LookupFieldDto(null, "someBoolean", LookupFieldType.VALUE));
        lookups.add(new LookupDto("By boolean", false, false, lookupFields, true, "byBool", asList("someBoolean")));

        lookupFields = new ArrayList<>();
        lookupFields.add(new LookupFieldDto(null, "someString", LookupFieldType.VALUE));
        lookups.add(new LookupDto("By unique String", true, false, lookupFields, true, "byUniqueString", asList("someString")));

        lookupFields = new ArrayList<>();
        lookupFields.add(new LookupFieldDto(null, "someBoolean", LookupFieldType.VALUE));
        lookupFields.add(new LookupFieldDto(null, "someDateTime", LookupFieldType.RANGE));
        lookupFields.add(new LookupFieldDto(null, "someString", LookupFieldType.SET));
        lookupFields.add(new LookupFieldDto(null, "someList", LookupFieldType.VALUE));
        lookups.add(new LookupDto("Combined", false, false, lookupFields, true));

        lookupFields = new ArrayList<>();
        lookupFields.add(new LookupFieldDto(null, "someInt", LookupFieldType.VALUE, "<="));
        lookups.add(new LookupDto("With custom operator", false, false, lookupFields, true, "customOperator", asList("someInt")));

        lookupFields = new ArrayList<>();
        lookupFields.add(new LookupFieldDto(null, "someString", LookupFieldType.VALUE, "matches()"));
        lookups.add(new LookupDto("With matches", false, false, lookupFields, true, "matchesOperator", asList("someString")));

        lookupFields = new ArrayList<>();
        lookupFields.add(new LookupFieldDto(null, "someString", LookupFieldType.VALUE,
                Constants.Operators.MATCHES_CASE_INSENSITIVE));
        lookups.add(new LookupDto("With matches case insensitive", false, false, lookupFields, true, "matchesOperatorCI",
                singletonList("someString")));

        entityService.addLookups(entityDto.getId(), lookups);
        entityService.commitChanges(entityDto.getId());
        generator.regenerateMdsDataBundle();

        getLogger().info("Entities ready for testing");
    }

    private void clearEntities() {
        getLogger().info("Cleaning up entities");

        for (EntityDto entity : entityService.listEntities()) {
            if (!entity.isDDE()) {
                entityService.deleteEntity(entity.getId());
            }
        }
    }

    private void updateInstance(Object instance, Boolean boolField, String stringField, String capitalizedStrField, List listField,
                                DateTime dateTimeField, LocalDate localDateField, Map map, Period period,
                                Byte[] blob, Date dateField, Double decimalField, Time timeField, Integer intField,
                                Object enumVal, java.time.LocalDate javaDateField, LocalDateTime javaDateTimeField)
            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        PropertyUtils.setProperty(instance, "someBoolean", boolField);
        PropertyUtils.setProperty(instance, "someString", stringField);
        PropertyUtil.safeSetProperty(instance, "CapitalName", capitalizedStrField);
        PropertyUtils.setProperty(instance, "someList", listField);
        PropertyUtils.setProperty(instance, "someDateTime", dateTimeField);
        PropertyUtils.setProperty(instance, "someJavaDateTime", javaDateTimeField);
        PropertyUtils.setProperty(instance, "someLocalDate", localDateField);
        PropertyUtils.setProperty(instance, "someJavaDate", javaDateField);
        PropertyUtils.setProperty(instance, "someMap", map);
        PropertyUtils.setProperty(instance, "somePeriod", period);
        PropertyUtils.setProperty(instance, "someBlob", blob);
        PropertyUtils.setProperty(instance, "someDate", dateField);
        PropertyUtils.setProperty(instance, "someDecimal", decimalField);
        PropertyUtils.setProperty(instance, "someTime", timeField);
        PropertyUtils.setProperty(instance, "someInt", intField);
        PropertyUtils.setProperty(instance, "someEnum", enumVal);
    }

    private void assertInstance(Object instance, Boolean boolField, String stringField, String capitalizedStrField, List listField,
                                DateTime dateTimeField, LocalDate localDateField, Map map, Period period,
                                Byte[] blob, Date dateField, Double decimalField, Time timeField, Integer intField,
                                Object enumVal, java.time.LocalDate javaDateField, LocalDateTime javaDateTimeField)
            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        assertNotNull(instance);
        assertEquals(boolField, PropertyUtils.getProperty(instance, "someBoolean"));
        assertEquals(stringField, PropertyUtils.getProperty(instance, "someString"));
        assertEquals(capitalizedStrField, PropertyUtil.safeGetProperty(instance, "CapitalName"));
        assertEquals(listField, PropertyUtils.getProperty(instance, "someList"));
        assertEquals(dateTimeField, PropertyUtils.getProperty(instance, "someDateTime"));
        assertEquals(map, PropertyUtils.getProperty(instance, "someMap"));
        assertEquals(period, PropertyUtils.getProperty(instance, "somePeriod"));
        assertEquals(localDateField, PropertyUtils.getProperty(instance, "someLocalDate"));
        assertEquals(dateField, PropertyUtils.getProperty(instance, "someDate"));
        assertEquals(decimalField, PropertyUtils.getProperty(instance, "someDecimal"));
        assertEquals(timeField, PropertyUtils.getProperty(instance, "someTime"));
        assertEquals(intField, PropertyUtils.getProperty(instance, "someInt"));
        assertEquals(enumVal, PropertyUtils.getProperty(instance, "someEnum"));
        assertEquals(javaDateField, PropertyUtils.getProperty(instance, "someJavaDate"));
        assertEquals(javaDateTimeField, PropertyUtils.getProperty(instance, "someJavaDateTime"));

        // assert blob
        Object blobValue = service.getDetachedField(instance, "someBlob");
        assertEquals(Arrays.toString(blob), Arrays.toString((Byte[]) blobValue));
    }

    private Object toEnum(Class entityClass, String str) throws NoSuchFieldException {
        Class enumClass;
        java.lang.reflect.Field someEnumField = entityClass.getDeclaredField("someEnum");
        if (someEnumField.getType().isEnum()) {
            enumClass = someEnumField.getType();
        } else {
            ParameterizedType type = (ParameterizedType) someEnumField.getGenericType();
            enumClass = (Class)type.getActualTypeArguments()[0];
        }
        Object[] constants = enumClass.getEnumConstants();
        for (Object constant : constants) {
            if (constant.toString().equals(str)) {
                return constant;
            }
        }

        fail("Value [" + str + "] not found in enum " + enumClass.getName());

        return null;
    }

    private Field findFieldByName(Collection<Field> fields, String name) {
        for (Field field : fields) {
            if (StringUtils.equals(field.getName(), name)) {
                return field;
            }
        }
        return null;
    }

    private void setCacheType(String type) throws IOException {
        try (FileOutputStream outputStream = new FileOutputStream(configurationFile)) {
            Properties datanucleusProps = coreConfigurationService.loadDatanucleusConfig();
            if (type != null) {
                datanucleusProps.setProperty("datanucleus.cache.level2.type", type);
            } else {
                datanucleusProps.remove("datanucleus.cache.level2.type");
            }
            datanucleusProps.store(outputStream, null);
        }
    }

    private void assertInstanceOne(Object instance, Class objClass) throws Exception {
        assertInstance(instance, true, "trueNow", "trueNowCp", asList("1", "2", "3"),
                NOW, LD_NOW, TEST_MAP, TEST_PERIOD, BYTE_ARRAY_VALUE,
                DATE_NOW, DOUBLE_VALUE_1, MORNING_TIME, 1, toEnum(objClass, "one"),
                JAVA_LD_NOW, JAVA_NOW);
    }

    private void assertInstanceTwo(Object instance, Class objClass) throws Exception {
        assertInstance(instance, true, "trueInRange", "trueInRangeCp", asList("2", "4"),
                NOW.plusHours(1), LD_NOW.plusDays(1), TEST_MAP, TEST_PERIOD, BYTE_ARRAY_VALUE,
                DATE_NOW, DOUBLE_VALUE_1, MORNING_TIME, 2, toEnum(objClass, "two"),
                JAVA_LD_NOW.plusDays(1), JAVA_NOW.plusHours(1));
    }

    private void assertInstanceThree(Object instance, Class objClass) throws Exception {
        assertInstance(instance, false, "falseInRange", "falseInRangeCp", Collections.emptyList(),
                NOW.plusHours(2), LD_NOW.plusDays(1), null, TEST_PERIOD, BYTE_ARRAY_VALUE,
                DATE_TOMORROW, DOUBLE_VALUE_2, NIGHT_TIME, 2, toEnum(objClass, "three"),
                JAVA_LD_NOW.plusDays(2), JAVA_NOW.plusHours(2));
    }

    private void assertInstanceFour(Object instance, Class objClass) throws Exception {
        assertInstance(instance, true, "trueOutOfRange", "trueOutOfRangeCp", Collections.emptyList(),
                NOW.plusHours(3), LD_NOW.plusDays(10), null, TEST_PERIOD, BYTE_ARRAY_VALUE,
                DATE_TOMORROW, DOUBLE_VALUE_2, NIGHT_TIME, 3, toEnum(objClass, "one"),
                JAVA_LD_NOW.plusDays(3), JAVA_NOW.plusHours(3));
    }

    private void assertInstanceFive(Object instance, Class objClass) throws Exception {
        assertInstance(instance, true, "notInSet", "notInSetCp", Collections.emptyList(),
                NOW.plusHours(4), LD_NOW, null, TEST_PERIOD, BYTE_ARRAY_VALUE,
                DATE_NOW, DOUBLE_VALUE_2, MORNING_TIME, 4, toEnum(objClass, "two"),
                JAVA_LD_NOW.plusDays(4), JAVA_NOW.plusHours(4));
    }

    private void assertInstanceOneDotOne(Object instance, Class objClass) throws Exception {
        assertInstance(instance, false, "anotherString", "anotherStringCp", asList("4", "5"),
                YEAR_LATER, LD_YEAR_AGO, TEST_MAP2, NEW_PERIOD, BYTE_ARRAY_VALUE,
                DATE_TOMORROW, DOUBLE_VALUE_2, NIGHT_TIME, 10, toEnum(objClass, "two"),
                JAVA_LD_NOW.plusDays(5), JAVA_NOW.plusHours(5));
    }
}