/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package org.apache.geode.pdx;

import static org.apache.geode.distributed.ConfigurationProperties.DISTRIBUTED_SYSTEM_ID;
import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Properties;

import org.junit.Test;
import org.junit.experimental.categories.Category;

import org.apache.geode.DataSerializer;
import org.apache.geode.cache.AttributesFactory;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionFactory;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.Scope;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.ClientCacheFactory;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.apache.geode.cache.client.PoolFactory;
import org.apache.geode.cache.client.PoolManager;
import org.apache.geode.cache.client.internal.PoolImpl;
import org.apache.geode.cache.server.CacheServer;
import org.apache.geode.internal.AvailablePortHelper;
import org.apache.geode.internal.HeapDataOutputStream;
import org.apache.geode.internal.PdxSerializerObject;
import org.apache.geode.internal.serialization.KnownVersion;
import org.apache.geode.pdx.internal.AutoSerializableManager;
import org.apache.geode.test.dunit.Host;
import org.apache.geode.test.dunit.Invoke;
import org.apache.geode.test.dunit.NetworkUtils;
import org.apache.geode.test.dunit.SerializableCallable;
import org.apache.geode.test.dunit.SerializableRunnable;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase;
import org.apache.geode.test.junit.categories.SerializationTest;

@Category({SerializationTest.class})
public class PdxClientServerDUnitTest extends JUnit4CacheTestCase {

  public PdxClientServerDUnitTest() {
    super();
  }

  @Test
  public void testSimplePut() {
    Host host = Host.getHost(0);
    VM vm0 = host.getVM(0);
    VM vm1 = host.getVM(1);
    VM vm2 = host.getVM(2);
    VM vm3 = host.getVM(3);

    vm0.invoke(() -> createServerRegion(SimpleClass.class));
    int port = createServerAccessor(vm3);
    createClientRegion(vm1, port);
    createClientRegion(vm2, port);

    vm1.invoke(() -> {
      Region r = getRootRegion("testSimplePdx");
      r.put(1, new SimpleClass(57, (byte) 3));
      return null;
    });
    final SerializableCallable checkValue = new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        Region r = getRootRegion("testSimplePdx");
        assertEquals(new SimpleClass(57, (byte) 3), r.get(1));
        return null;
      }
    };
    vm2.invoke(checkValue);
    vm0.invoke(checkValue);
    vm1.invoke(checkValue);

  }

  /**
   * Test what happens to the client type registry if the server is restarted and PDX serialization
   * for a class has changed. This was reported in Pivotal bug #47338
   */
  @Test
  public void testNonPersistentServerRestart() {
    Host host = Host.getHost(0);
    VM vm0 = host.getVM(0);
    VM vm1 = host.getVM(1);
    VM vm2 = host.getVM(2);

    final int port = vm0.invoke(() -> createServerRegion(SimpleClass.class));
    createClientRegion(vm1, port, true);

    // Define a PDX type with 2 fields that will be cached on the client
    vm1.invoke(() -> {
      Region r = getRootRegion("testSimplePdx");
      r.put(1, new PdxType2(1, 1));
      r.get(1);
      return null;
    });

    closeCache(vm0);

    // GEODE-1037: make sure the client knows that the server
    // is gone
    vm1.invoke(() -> {
      Region r = getRootRegion("testSimplePdx");
      // make sure the client has reconnected to the server
      // by performing a get() on a key the client cache does
      // not contain
      try {
        r.get(4);
        throw new Error("expected an exception to be thrown");
      } catch (Exception expected) {
      }
    });

    createServerRegion(vm0, port);
    createClientRegion(vm2, port, true);

    // Now defined a PDX type with only 1 field. This should
    // reuse the same type id because the server was restarted.
    vm2.invoke(() -> {
      Region r = getRootRegion("testSimplePdx");
      r.put(3, new PdxType1(3));
      r.get(3);
      return null;
    });

    // See what happens when vm1 tries to read the type.
    // If it cached the type id it will try to read a PdxType2
    // and fail with a ServerOperationException having a
    // PdxSerializationException "cause"
    vm1.invoke(() -> {
      Region r = getRootRegion("testSimplePdx");

      // now get object 3, which was put in the server by vm2
      PdxType1 results = (PdxType1) r.get(3);
      assertEquals(3, results.int1);

      // Add another field to make sure the write path doesn't have
      // something cached on vm1.
      r.put(5, new PdxType2(5, 5));
      return null;
    });

    // Make sure vm2 can read what vm1 has written
    vm2.invoke(() -> {
      Region r = getRootRegion("testSimplePdx");
      PdxType2 results = (PdxType2) r.get(5);
      assertEquals(5, results.int1);
      assertEquals(5, results.int2);
      return null;
    });
  }

  /**
   * Test of bug 47338 - what happens to the client type registry if the server is restarted.
   */
  @Test
  public void testNonPersistentServerRestartAutoSerializer() {
    Host host = Host.getHost(0);
    VM vm0 = host.getVM(0);
    VM vm1 = host.getVM(1);
    VM vm2 = host.getVM(2);

    System.setProperty(AutoSerializableManager.NO_HARDCODED_EXCLUDES_PARAM, "true");
    Invoke.invokeInEveryVM(new SerializableRunnable() {
      @Override
      public void run() {
        System.setProperty(AutoSerializableManager.NO_HARDCODED_EXCLUDES_PARAM, "true");
      }
    });
    try {
      String[] patterns =
          new String[] {"org.apache.geode.pdx.PdxClientServerDUnitTest.AutoPdxType.*"};
      int port = createServerRegion(vm0);
      createClientRegion(vm1, port, true, patterns);

      // Define a PDX type with 2 fields that will be cached on the client
      vm1.invoke(() -> {
        Region r = getRootRegion("testSimplePdx");
        r.put(1, new AutoPdxType2(1, 1));
        r.get(1);
        return null;
      });

      closeCache(vm0);
      createServerRegion(vm0, port);
      createClientRegion(vm2, port, true, patterns);

      // Now defined a PDX type with only 1 field. This should
      // reuse the same type id because the server was restarted.
      vm2.invoke(() -> {
        Region r = getRootRegion("testSimplePdx");
        r.put(3, new AutoPdxType1(3));
        r.get(3);
        return null;
      });

      // See what happens when vm1 tries to read the type.
      // If it cached the type id it will have problems.
      vm1.invoke(() -> {
        Region r = getRootRegion("testSimplePdx");
        try {
          r.get(4);
        } catch (Exception expected) {
          // The client may not have noticed the server go away and come
          // back. Let's trigger the exception so the client will retry.
        }
        AutoPdxType1 results = (AutoPdxType1) r.get(3);
        assertEquals(3, results.int1);

        // Add another field to make sure the write path doesn't have
        // something cached on vm1.
        r.put(5, new AutoPdxType2(5, 5));
        return null;
      });

      // Make sure vm2 can read what vm1 has written
      vm2.invoke(() -> {
        Region r = getRootRegion("testSimplePdx");
        AutoPdxType2 results = (AutoPdxType2) r.get(5);
        assertEquals(5, results.int1);
        assertEquals(5, results.int2);
        return null;
      });
    } finally {
      System.setProperty(AutoSerializableManager.NO_HARDCODED_EXCLUDES_PARAM, "false");
      Invoke.invokeInEveryVM(new SerializableRunnable() {
        @Override
        public void run() {
          System.setProperty(AutoSerializableManager.NO_HARDCODED_EXCLUDES_PARAM, "false");
        }
      });
    }
  }

  /**
   * Test that we through an exception if one of the servers has persistent regions but not a
   * persistent registry.
   */
  @Test
  public void testServersWithPersistence() {
    Host host = Host.getHost(0);
    VM vm0 = host.getVM(0);
    VM vm1 = host.getVM(1);
    VM vm2 = host.getVM(2);
    VM vm3 = host.getVM(3);

    createServerRegionWithPersistence(vm0, false);
    int port = createServerAccessor(vm1);
    createClientRegion(vm2, port);
    createClientRegion(vm3, port);

    SerializableCallable createValue = new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        Region r = getRootRegion("testSimplePdx");
        try {
          r.put(1, new SimpleClass(57, (byte) 3));
          fail("should have received an exception");
        } catch (PdxInitializationException expected) {
          // do nothing
        }
        return null;
      }
    };
  }

  private void closeCache(VM vm) {
    vm.invoke(() -> {
      closeCache();
      return null;
    });
  }

  @Test
  public void testSimplePdxInstancePut() {
    Host host = Host.getHost(0);
    VM vm0 = host.getVM(0);
    VM vm1 = host.getVM(1);
    VM vm2 = host.getVM(2);

    int port = vm0.invoke(() -> createServerRegion(SimpleClass.class));
    createClientRegion(vm1, port);
    createClientRegion(vm2, port);

    vm1.invoke(() -> {
      Region r = getRootRegion("testSimplePdx");
      r.put(1, new SimpleClass(57, (byte) 3));
      return null;
    });
    final SerializableCallable checkValue = new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        Region r = getRootRegion("testSimplePdx");
        Boolean previousPdxReadSerializedFlag = cache.getPdxReadSerializedOverride();
        cache.setPdxReadSerializedOverride(true);
        try {
          Object v = r.get(1);
          if (!(v instanceof PdxInstance)) {
            fail("expected v " + v.getClass() + " to be a PdxInstance");
          }
          PdxInstance piv = (PdxInstance) v;
          assertEquals(new SimpleClass(57, (byte) 3), piv.getObject());
          Object v2 = r.get(1);
          if (v == v2) {
            fail("expected v and v2 to have a different identity");
          }
          assertEquals(v, v2);
        } finally {
          cache.setPdxReadSerializedOverride(previousPdxReadSerializedFlag);
        }
        return null;
      }
    };
    vm2.invoke(checkValue);

    vm0.invoke(checkValue);

  }

  /**
   * Test to make sure that types are sent to all pools, even if they are in multiple distributed
   * systems.
   */
  @Test
  public void testMultipleServerDSes() throws Exception {
    Host host = Host.getHost(0);
    final VM vm0 = host.getVM(0);
    VM vm1 = host.getVM(1);
    VM vm2 = host.getVM(2);
    VM vm3 = host.getVM(3);

    final int port1 = createLonerServerRegion(vm0, "region1", "1");
    final int port2 = createLonerServerRegion(vm1, "region2", "2");

    SerializableCallable createRegion = new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        Properties props = new Properties();
        props.setProperty(MCAST_PORT, "0");
        props.setProperty(LOCATORS, "");
        getSystem(props);
        Cache cache = getCache();
        PoolFactory pf = PoolManager.createFactory();
        pf.addServer(NetworkUtils.getServerHostName(vm0.getHost()), port1);
        pf.create("pool1");

        pf = PoolManager.createFactory();
        pf.addServer(NetworkUtils.getServerHostName(vm0.getHost()), port2);
        pf.create("pool2");

        AttributesFactory af = new AttributesFactory();
        af.setPoolName("pool1");
        cache.createRegion("region1", af.create());

        af = new AttributesFactory();
        af.setPoolName("pool2");
        cache.createRegion("region2", af.create());
        return null;
      }
    };
    vm2.invoke(createRegion);
    vm3.invoke(createRegion);
    createRegion.call();

    // Serialize an object and put it in both regions, sending
    // the event to each pool
    vm2.invoke(() -> {
      HeapDataOutputStream bytes = new HeapDataOutputStream(KnownVersion.CURRENT);
      Region r1 = getRootRegion("region1");
      r1.put(1, new SimpleClass(57, (byte) 3));
      Region r2 = getRootRegion("region2");
      r2.put(1, new SimpleClass(57, (byte) 3));
      return null;
    });

    // Make sure we get deserialize the value in a different client
    vm3.invoke(() -> {
      Region r = getRootRegion("region1");
      assertEquals(new SimpleClass(57, (byte) 3), r.get(1));
      return null;
    });

    // Make sure we can get the entry in the current member
    Region r = getRootRegion("region2");
    assertEquals(new SimpleClass(57, (byte) 3), r.get(1));
  }

  @Test
  public void testUserSerializesObject() {
    Host host = Host.getHost(0);
    VM vm0 = host.getVM(0);
    VM vm1 = host.getVM(1);
    VM vm2 = host.getVM(2);

    int port = vm0.invoke(() -> createServerRegion(Object.class));
    createClientRegion(vm1, port);
    createClientRegion(vm2, port);

    vm1.invoke(() -> {
      HeapDataOutputStream out = new HeapDataOutputStream(KnownVersion.CURRENT);
      DataSerializer.writeObject(new SimpleClass(57, (byte) 3), out);
      byte[] bytes = out.toByteArray();
      Region r = getRootRegion("testSimplePdx");
      r.put(1, bytes);
      return null;
    });

    SerializableCallable checkValue = new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        Region r = getRootRegion("testSimplePdx");
        byte[] bytes = (byte[]) r.get(1);
        DataInputStream bis = new DataInputStream(new ByteArrayInputStream(bytes));
        Object result = DataSerializer.readObject(bis);
        assertEquals(new SimpleClass(57, (byte) 3), result);
        return null;
      }
    };
    vm2.invoke(checkValue);

    vm0.invoke(checkValue);
  }

  /**
   * Test that we still use the client type registry, even if pool is created late.
   */
  @Test
  public void testLatePoolCreation() {
    Host host = Host.getHost(0);
    final VM vm0 = host.getVM(0);
    VM vm1 = host.getVM(1);
    VM vm2 = host.getVM(2);

    final int port = vm0.invoke(() -> createServerRegion(SimpleClass.class));
    SerializableCallable createRegion = new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        Properties props = new Properties();
        props.setProperty(MCAST_PORT, "0");
        props.setProperty(LOCATORS, "");
        getSystem(props);
        Cache cache = getCache();
        PoolFactory pf = PoolManager.createFactory();
        pf.addServer(NetworkUtils.getServerHostName(vm0.getHost()), port);
        pf.create("pool");

        AttributesFactory af = new AttributesFactory();
        af.setPoolName("pool");
        cache.createRegion("testSimplePdx", af.create());
        return null;
      }
    };
    vm1.invoke(createRegion);
    vm2.invoke(createRegion);

    vm1.invoke(() -> {
      Region r = getRootRegion("testSimplePdx");
      r.put(1, new SimpleClass(57, (byte) 3));
      return null;
    });
    final SerializableCallable checkValue = new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        Region r = getRootRegion("testSimplePdx");
        assertEquals(new SimpleClass(57, (byte) 3), r.get(1));
        return null;
      }
    };
    vm2.invoke(checkValue);

    vm0.invoke(checkValue);
  }

  /**
   * Test that we throw an exception if someone tries to create a pool after we were forced to use a
   * peer type registry.
   */
  @Test
  public void testExceptionWithPoolAfterTypeRegistryCreation() {
    Host host = Host.getHost(0);
    final VM vm0 = host.getVM(0);
    VM vm1 = host.getVM(1);

    final int port = vm0.invoke(() -> createServerRegion(SimpleClass.class));
    SerializableCallable createRegion = new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        Properties props = new Properties();
        props.setProperty(MCAST_PORT, "0");
        props.setProperty(LOCATORS, "");
        getSystem(props);
        Cache cache = getCache();
        HeapDataOutputStream out = new HeapDataOutputStream(KnownVersion.CURRENT);
        DataSerializer.writeObject(new SimpleClass(57, (byte) 3), out);

        PoolFactory pf = PoolManager.createFactory();
        pf.addServer(NetworkUtils.getServerHostName(vm0.getHost()), port);
        try {
          pf.create("pool");
          fail("should have received an exception");
        } catch (PdxInitializationException expected) {
          // do nothing
        }
        return null;
      }
    };

    vm1.invoke(createRegion);
  }

  @Test
  public void testCacheRejectsJSonPdxInstanceViolatingValueConstraint() {
    Host host = Host.getHost(0);
    VM vm0 = host.getVM(0);
    VM vm1 = host.getVM(1);

    final int port = vm0.invoke(() -> createServerRegion(SimpleClass.class));

    vm0.invoke("put value in region", () -> {
      Region r = basicGetCache().getRegion("testSimplePdx");
      String className = "objects.PersonWithoutID";
      try {
        r.put("pdxObject", getTypedJSONPdxInstance(className));
        fail("expected a ClassCastException");
      } catch (ClassCastException e) {
        assertTrue("wrong ClassCastException message: " + e.getMessage(),
            e.getMessage().contains(className));
      }
      return null;
    });
  }


  public PdxInstance getTypedJSONPdxInstance(String className) throws Exception {

    String aRESTishDoc = "{\"@type\": \" " + className
        + "\" , \" firstName\" : \" John\" , \" lastName\" : \" Smith\" , \" age\" : 25 }";
    PdxInstance pdxInstance = JSONFormatter.fromJSON(aRESTishDoc);

    return pdxInstance;
  }

  private int createServerRegion(final Class constraintClass) throws IOException {
    CacheFactory cf = new CacheFactory(getDistributedSystemProperties());
    Cache cache = getCache(cf);
    RegionFactory rf = cache.createRegionFactory(RegionShortcut.REPLICATE);
    rf.setValueConstraint(constraintClass);
    rf.create("testSimplePdx");
    CacheServer server = cache.addCacheServer();
    int port = AvailablePortHelper.getRandomAvailableTCPPort();
    server.setPort(port);
    server.start();
    return port;
  }

  private int createServerRegion(VM vm) {
    SerializableCallable createRegion = new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        AttributesFactory af = new AttributesFactory();
        af.setScope(Scope.DISTRIBUTED_ACK);
        af.setDataPolicy(DataPolicy.REPLICATE);
        createRootRegion("testSimplePdx", af.create());
        CacheServer server = getCache().addCacheServer();
        int port = AvailablePortHelper.getRandomAvailableTCPPort();
        server.setPort(port);
        server.start();
        return port;
      }
    };

    return (Integer) vm.invoke(createRegion);
  }

  private int createServerRegion(VM vm, final int port) {
    SerializableCallable createRegion = new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        AttributesFactory af = new AttributesFactory();
        af.setScope(Scope.DISTRIBUTED_ACK);
        af.setDataPolicy(DataPolicy.REPLICATE);
        createRootRegion("testSimplePdx", af.create());

        CacheServer server = getCache().addCacheServer();
        server.setPort(port);
        server.start();
        return port;
      }
    };

    return (Integer) vm.invoke(createRegion);
  }

  private int createServerRegionWithPersistence(VM vm, final boolean persistentPdxRegistry) {
    SerializableCallable createRegion = new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        CacheFactory cf = new CacheFactory();
        if (persistentPdxRegistry) {
          cf.setPdxPersistent(true).setPdxDiskStore("store");
        }
        //
        Cache cache = getCache(cf);
        cache.createDiskStoreFactory().setDiskDirs(getDiskDirs()).create("store");

        AttributesFactory af = new AttributesFactory();
        af.setScope(Scope.DISTRIBUTED_ACK);
        af.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE);
        af.setDiskStoreName("store");
        createRootRegion("testSimplePdx", af.create());

        CacheServer server = getCache().addCacheServer();
        int port = AvailablePortHelper.getRandomAvailableTCPPort();
        server.setPort(port);
        server.start();
        return port;
      }
    };

    return (Integer) vm.invoke(createRegion);
  }

  private int createServerAccessor(VM vm) {
    SerializableCallable createRegion = new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        AttributesFactory af = new AttributesFactory();
        af.setScope(Scope.DISTRIBUTED_ACK);
        af.setDataPolicy(DataPolicy.EMPTY);
        createRootRegion("testSimplePdx", af.create());

        CacheServer server = getCache().addCacheServer();
        int port = AvailablePortHelper.getRandomAvailableTCPPort();
        server.setPort(port);
        server.start();
        return port;
      }
    };

    return (Integer) vm.invoke(createRegion);
  }

  private int createLonerServerRegion(VM vm, final String regionName, final String dsId) {
    SerializableCallable createRegion = new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        Properties props = new Properties();
        props.setProperty(LOCATORS, "");
        props.setProperty(DISTRIBUTED_SYSTEM_ID, dsId);
        getSystem(props);
        AttributesFactory af = new AttributesFactory();
        af.setScope(Scope.DISTRIBUTED_ACK);
        af.setDataPolicy(DataPolicy.REPLICATE);
        createRootRegion(regionName, af.create());

        CacheServer server = getCache().addCacheServer();
        int port = AvailablePortHelper.getRandomAvailableTCPPort();
        server.setPort(port);
        server.start();
        return port;
      }
    };

    return (Integer) vm.invoke(createRegion);
  }

  private void createClientRegion(final VM vm, final int port) {
    createClientRegion(vm, port, false);
  }

  private void createClientRegion(final VM vm, final int port, final boolean setPdxTypeClearProp,
      final String... autoSerializerPatterns) {
    SerializableCallable createRegion = new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        if (setPdxTypeClearProp) {
          System.setProperty(PoolImpl.ON_DISCONNECT_CLEAR_PDXTYPEIDS, "true");
        }
        ClientCacheFactory cf = new ClientCacheFactory();
        cf.addPoolServer(NetworkUtils.getServerHostName(vm.getHost()), port);
        if (autoSerializerPatterns != null && autoSerializerPatterns.length != 0) {
          cf.setPdxSerializer(new ReflectionBasedAutoSerializer(autoSerializerPatterns));
        }
        ClientCache cache = getClientCache(cf);
        cache.createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY).create("testSimplePdx");
        return null;
      }
    };
    vm.invoke(createRegion);
  }

  public static class PdxType1 implements PdxSerializable {
    int int1;

    public PdxType1() {

    }

    public PdxType1(int int1) {
      this.int1 = int1;
    }

    @Override
    public void toData(PdxWriter writer) {
      writer.writeInt("int1", int1);

    }

    @Override
    public void fromData(PdxReader reader) {
      int1 = reader.readInt("int1");

    }
  }

  public static class PdxType2 implements PdxSerializable {
    int int1;
    int int2;


    public PdxType2() {

    }

    public PdxType2(int int1, int int2) {
      super();
      this.int1 = int1;
      this.int2 = int2;
    }

    @Override
    public void toData(PdxWriter writer) {
      writer.writeInt("int1", int1);
      writer.writeInt("int2", int2);
    }

    @Override
    public void fromData(PdxReader reader) {
      int1 = reader.readInt("int1");
      int2 = reader.readInt("int2");
    }
  }

  public static class AutoPdxType1 implements PdxSerializerObject {
    public int int1;

    public AutoPdxType1() {

    }

    public AutoPdxType1(int int1) {
      this.int1 = int1;
    }
  }

  public static class AutoPdxType2 implements PdxSerializerObject {
    public int int1;
    public int int2;


    public AutoPdxType2() {

    }

    public AutoPdxType2(int int1, int int2) {
      this.int1 = int1;
      this.int2 = int2;
    }
  }
}
