You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2015/09/03 07:54:09 UTC

[1/4] ignite git commit: ignite-1273: fixed cyclic references processing by PortableMarshaller and ability to modify array fields returned by PortableBuilder

Repository: ignite
Updated Branches:
  refs/heads/master 8bd86447e -> 6ac9557ef


http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableBuilderAdditionalSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableBuilderAdditionalSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableBuilderAdditionalSelfTest.java
index 488361c..61ec714 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableBuilderAdditionalSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableBuilderAdditionalSelfTest.java
@@ -22,6 +22,7 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import java.lang.reflect.Field;
+import java.math.BigDecimal;
 import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -38,6 +39,8 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgnitePortables;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.portable.builder.PortableBuilderEnum;
+import org.apache.ignite.internal.portable.builder.PortableBuilderImpl;
 import org.apache.ignite.internal.portable.mutabletest.GridPortableMarshalerAwareTestClass;
 import org.apache.ignite.internal.processors.cache.portable.CacheObjectPortableProcessorImpl;
 import org.apache.ignite.internal.processors.cache.portable.IgnitePortablesImpl;
@@ -237,10 +240,214 @@ public class GridPortableBuilderAdditionalSelfTest extends GridCommonAbstractTes
     /**
      *
      */
-    public void testSimpleArrayModification() {
+    public void testDateArrayModification() {
         TestObjectAllTypes obj = new TestObjectAllTypes();
 
-        obj.strArr = new String[]{"a", "a", "a"};
+        obj.dateArr =  new Date[] {new Date(11111), new Date(11111), new Date(11111)};
+
+        PortableBuilderImpl mutObj = wrap(obj);
+
+        Date[] arr = mutObj.getField("dateArr");
+        arr[0] = new Date(22222);
+
+        TestObjectAllTypes res = mutObj.build().deserialize();
+
+        Assert.assertArrayEquals(new Date[] {new Date(22222), new Date(11111), new Date(11111)}, res.dateArr);
+    }
+
+    /**
+     *
+     */
+    public void testUUIDArrayModification() {
+        TestObjectAllTypes obj = new TestObjectAllTypes();
+
+        obj.uuidArr = new UUID[] {new UUID(1, 1), new UUID(1, 1), new UUID(1, 1)};
+
+        PortableBuilderImpl mutObj = wrap(obj);
+
+        UUID[] arr = mutObj.getField("uuidArr");
+        arr[0] = new UUID(2, 2);
+
+        TestObjectAllTypes res = mutObj.build().deserialize();
+
+        Assert.assertArrayEquals(new UUID[] {new UUID(2, 2), new UUID(1, 1), new UUID(1, 1)}, res.uuidArr);
+    }
+
+    /**
+     *
+     */
+    public void testDecimalArrayModification() {
+        TestObjectAllTypes obj = new TestObjectAllTypes();
+
+        obj.bdArr = new BigDecimal[] {new BigDecimal(1000), new BigDecimal(1000), new BigDecimal(1000)};
+
+        PortableBuilderImpl mutObj = wrap(obj);
+
+        BigDecimal[] arr = mutObj.getField("bdArr");
+        arr[0] = new BigDecimal(2000);
+
+        TestObjectAllTypes res = mutObj.build().deserialize();
+
+        Assert.assertArrayEquals(new BigDecimal[] {new BigDecimal(1000), new BigDecimal(1000), new BigDecimal(1000)},
+            res.bdArr);
+    }
+
+    /**
+     *
+     */
+    public void testBooleanArrayModification() {
+        TestObjectAllTypes obj = new TestObjectAllTypes();
+
+        obj.zArr = new boolean[] {false, false, false};
+
+        PortableBuilderImpl mutObj = wrap(obj);
+
+        boolean[] arr = mutObj.getField("zArr");
+        arr[0] = true;
+
+        TestObjectAllTypes res = mutObj.build().deserialize();
+
+        boolean[] expected = new boolean[] {true, false, false};
+
+        assertEquals(expected.length, res.zArr.length);
+
+        for (int i = 0; i < expected.length; i++)
+            assertEquals(expected[i], res.zArr[i]);
+    }
+
+    /**
+     *
+     */
+    public void testCharArrayModification() {
+        TestObjectAllTypes obj = new TestObjectAllTypes();
+
+        obj.cArr = new char[] {'a', 'a', 'a'};
+
+        PortableBuilderImpl mutObj = wrap(obj);
+
+        char[] arr = mutObj.getField("cArr");
+        arr[0] = 'b';
+
+        TestObjectAllTypes res = mutObj.build().deserialize();
+
+        Assert.assertArrayEquals(new char[] {'b', 'a', 'a'}, res.cArr);
+    }
+
+    /**
+     *
+     */
+    public void testDoubleArrayModification() {
+        TestObjectAllTypes obj = new TestObjectAllTypes();
+
+        obj.dArr = new double[] {1.0, 1.0, 1.0};
+
+        PortableBuilderImpl mutObj = wrap(obj);
+
+        double[] arr = mutObj.getField("dArr");
+        arr[0] = 2.0;
+
+        TestObjectAllTypes res = mutObj.build().deserialize();
+
+        Assert.assertArrayEquals(new double[] {2.0, 1.0, 1.0}, res.dArr, 0);
+    }
+
+    /**
+     *
+     */
+    public void testFloatArrayModification() {
+        TestObjectAllTypes obj = new TestObjectAllTypes();
+
+        obj.fArr = new float[] {1.0f, 1.0f, 1.0f};
+
+        PortableBuilderImpl mutObj = wrap(obj);
+
+        float[] arr = mutObj.getField("fArr");
+        arr[0] = 2.0f;
+
+        TestObjectAllTypes res = mutObj.build().deserialize();
+
+        Assert.assertArrayEquals(new float[] {2.0f, 1.0f, 1.0f}, res.fArr, 0);
+    }
+
+    /**
+     *
+     */
+    public void testLongArrayModification() {
+        TestObjectAllTypes obj = new TestObjectAllTypes();
+
+        obj.lArr = new long[] {1, 1, 1};
+
+        PortableBuilderImpl mutObj = wrap(obj);
+
+        long[] arr = mutObj.getField("lArr");
+        arr[0] = 2;
+
+        TestObjectAllTypes res = mutObj.build().deserialize();
+
+        Assert.assertArrayEquals(new long[] {2, 1, 1}, res.lArr);
+    }
+
+    /**
+     *
+     */
+    public void testIntArrayModification() {
+        TestObjectAllTypes obj = new TestObjectAllTypes();
+
+        obj.iArr = new int[] {1, 1, 1};
+
+        PortableBuilderImpl mutObj = wrap(obj);
+
+        int[] arr = mutObj.getField("iArr");
+        arr[0] = 2;
+
+        TestObjectAllTypes res = mutObj.build().deserialize();
+
+        Assert.assertArrayEquals(new int[] {2, 1, 1}, res.iArr);
+    }
+
+    /**
+     *
+     */
+    public void testShortArrayModification() {
+        TestObjectAllTypes obj = new TestObjectAllTypes();
+
+        obj.sArr = new short[] {1, 1, 1};
+
+        PortableBuilderImpl mutObj = wrap(obj);
+
+        short[] arr = mutObj.getField("sArr");
+        arr[0] = 2;
+
+        TestObjectAllTypes res = mutObj.build().deserialize();
+
+        Assert.assertArrayEquals(new short[] {2, 1, 1}, res.sArr);
+    }
+
+    /**
+     *
+     */
+    public void testByteArrayModification() {
+        TestObjectAllTypes obj = new TestObjectAllTypes();
+
+        obj.bArr = new byte[] {1, 1, 1};
+
+        PortableBuilderImpl mutObj = wrap(obj);
+
+        byte[] arr = mutObj.getField("bArr");
+        arr[0] = 2;
+
+        TestObjectAllTypes res = mutObj.build().deserialize();
+
+        Assert.assertArrayEquals(new byte[] {2, 1, 1}, res.bArr);
+    }
+
+    /**
+     *
+     */
+    public void testStringArrayModification() {
+        TestObjectAllTypes obj = new TestObjectAllTypes();
+
+        obj.strArr = new String[] {"a", "a", "a"};
 
         PortableBuilderImpl mutObj = wrap(obj);
 
@@ -249,29 +456,27 @@ public class GridPortableBuilderAdditionalSelfTest extends GridCommonAbstractTes
 
         TestObjectAllTypes res = mutObj.build().deserialize();
 
-        Assert.assertArrayEquals(obj.strArr, res.strArr);
+        Assert.assertArrayEquals(new String[] {"b", "a", "a"}, res.strArr);
     }
 
     /**
      *
      */
     public void testModifyObjectArray() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-1273");
-
         TestObjectContainer obj = new TestObjectContainer();
-        obj.foo = new Object[]{"a"};
+        obj.foo = new Object[] {"a"};
 
         PortableBuilderImpl mutObj = wrap(obj);
 
         Object[] arr = mutObj.getField("foo");
 
-        Assert.assertArrayEquals(new Object[]{"a"}, arr);
+        Assert.assertArrayEquals(new Object[] {"a"}, arr);
 
         arr[0] = "b";
 
         TestObjectContainer res = mutObj.build().deserialize();
 
-        Assert.assertArrayEquals(new Object[] {"a"}, (Object[])res.foo);
+        Assert.assertArrayEquals(new Object[] {"b"}, (Object[])res.foo);
     }
 
     /**
@@ -280,7 +485,7 @@ public class GridPortableBuilderAdditionalSelfTest extends GridCommonAbstractTes
     public void testOverrideObjectArrayField() {
         PortableBuilderImpl mutObj = wrap(new TestObjectContainer());
 
-        Object[] createdArr = {mutObj, "a", 1, new String[] {"s", "s"}, new byte[]{1, 2}, new UUID(3, 0)};
+        Object[] createdArr = {mutObj, "a", 1, new String[] {"s", "s"}, new byte[] {1, 2}, new UUID(3, 0)};
 
         mutObj.setField("foo", createdArr.clone());
 
@@ -296,7 +501,7 @@ public class GridPortableBuilderAdditionalSelfTest extends GridCommonAbstractTes
      */
     public void testDeepArray() {
         TestObjectContainer obj = new TestObjectContainer();
-        obj.foo = new Object[]{new Object[]{"a", obj}};
+        obj.foo = new Object[] {new Object[] {"a", obj}};
 
         PortableBuilderImpl mutObj = wrap(obj);
 
@@ -633,7 +838,7 @@ public class GridPortableBuilderAdditionalSelfTest extends GridCommonAbstractTes
     public void testEnumArrayModification() {
         TestObjectAllTypes obj = new TestObjectAllTypes();
 
-        obj.enumArr = new TestObjectEnum[]{TestObjectEnum.A, TestObjectEnum.B};
+        obj.enumArr = new TestObjectEnum[] {TestObjectEnum.A, TestObjectEnum.B};
 
         PortableBuilderImpl mutObj = wrap(obj);
 
@@ -953,12 +1158,10 @@ public class GridPortableBuilderAdditionalSelfTest extends GridCommonAbstractTes
      *
      */
     public void testCyclicArrays() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-1273");
-
         TestObjectContainer obj = new TestObjectContainer();
 
         Object[] arr1 = new Object[1];
-        Object[] arr2 = new Object[]{arr1};
+        Object[] arr2 = new Object[] {arr1};
 
         arr1[0] = arr2;
 
@@ -976,7 +1179,6 @@ public class GridPortableBuilderAdditionalSelfTest extends GridCommonAbstractTes
      */
     @SuppressWarnings("TypeMayBeWeakened")
     public void testCyclicArrayList() {
-        fail("https://issues.apache.org/jira/browse/IGNITE-1273");
         TestObjectContainer obj = new TestObjectContainer();
 
         List<Object> arr1 = new ArrayList<>();

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableBuilderSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableBuilderSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableBuilderSelfTest.java
index 3ba0a92..7f23c1f 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableBuilderSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableBuilderSelfTest.java
@@ -28,6 +28,7 @@ import java.util.UUID;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgnitePortables;
 import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.portable.builder.PortableBuilderImpl;
 import org.apache.ignite.internal.portable.mutabletest.GridPortableTestClasses.TestObjectAllTypes;
 import org.apache.ignite.internal.portable.mutabletest.GridPortableTestClasses.TestObjectContainer;
 import org.apache.ignite.internal.portable.mutabletest.GridPortableTestClasses.TestObjectInner;

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableMarshallerSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableMarshallerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableMarshallerSelfTest.java
index 11e316a..c8287a0 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableMarshallerSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableMarshallerSelfTest.java
@@ -40,6 +40,7 @@ import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentSkipListSet;
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.portable.builder.PortableBuilderImpl;
 import org.apache.ignite.internal.util.GridUnsafe;
 import org.apache.ignite.internal.util.IgniteUtils;
 import org.apache.ignite.internal.util.lang.GridMapEntry;
@@ -68,6 +69,7 @@ import sun.misc.Unsafe;
 
 import static org.apache.ignite.internal.portable.PortableThreadLocalMemoryAllocator.THREAD_LOCAL_ALLOC;
 import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Portable marshaller tests.
@@ -1547,11 +1549,11 @@ public class GridPortableMarshallerSelfTest extends GridCommonAbstractTest {
 
         PortableObject copy = copy(po, F.<String, Object>asMap("bArr", new byte[]{1, 2, 3}));
 
-        assertArrayEquals(new byte[]{1, 2, 3}, copy.<byte[]>field("bArr"));
+        assertArrayEquals(new byte[] {1, 2, 3}, copy.<byte[]>field("bArr"));
 
         SimpleObject obj0 = copy.deserialize();
 
-        assertArrayEquals(new byte[]{1, 2, 3}, obj0.bArr);
+        assertArrayEquals(new byte[] {1, 2, 3}, obj0.bArr);
     }
 
     /**
@@ -1796,7 +1798,7 @@ public class GridPortableMarshallerSelfTest extends GridCommonAbstractTest {
 
         assertEquals("str555", obj0.str);
         assertEquals(newObj, obj0.inner);
-        assertArrayEquals(new byte[]{6, 7, 9}, obj0.bArr);
+        assertArrayEquals(new byte[] {6, 7, 9}, obj0.bArr);
     }
 
     /**
@@ -1832,7 +1834,7 @@ public class GridPortableMarshallerSelfTest extends GridCommonAbstractTest {
         assertEquals("str555", copy.<String>field("str"));
         assertEquals(newObj, copy.<PortableObject>field("inner").deserialize());
         assertEquals((short)2323, copy.<Short>field("s").shortValue());
-        assertArrayEquals(new byte[]{6, 7, 9}, copy.<byte[]>field("bArr"));
+        assertArrayEquals(new byte[] {6, 7, 9}, copy.<byte[]>field("bArr"));
         assertEquals((byte)111, copy.<Byte>field("b").byteValue());
 
         SimpleObject obj0 = copy.deserialize();
@@ -1841,7 +1843,7 @@ public class GridPortableMarshallerSelfTest extends GridCommonAbstractTest {
         assertEquals("str555", obj0.str);
         assertEquals(newObj, obj0.inner);
         assertEquals((short)2323, obj0.s);
-        assertArrayEquals(new byte[]{6, 7, 9}, obj0.bArr);
+        assertArrayEquals(new byte[] {6, 7, 9}, obj0.bArr);
         assertEquals((byte)111, obj0.b);
     }
 
@@ -2239,6 +2241,53 @@ public class GridPortableMarshallerSelfTest extends GridCommonAbstractTest {
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    public void testCyclicReferencesMarshalling() throws Exception {
+        PortableMarshaller marsh = new PortableMarshaller();
+
+        SimpleObject obj = simpleObject();
+
+        obj.bArr = obj.inner.bArr;
+        obj.cArr = obj.inner.cArr;
+        obj.boolArr = obj.inner.boolArr;
+        obj.sArr = obj.inner.sArr;
+        obj.strArr = obj.inner.strArr;
+        obj.iArr = obj.inner.iArr;
+        obj.lArr = obj.inner.lArr;
+        obj.fArr = obj.inner.fArr;
+        obj.dArr = obj.inner.dArr;
+        obj.dateArr = obj.inner.dateArr;
+        obj.uuidArr = obj.inner.uuidArr;
+        obj.objArr = obj.inner.objArr;
+        obj.bdArr = obj.inner.bdArr;
+        obj.map = obj.inner.map;
+        obj.col = obj.inner.col;
+        obj.mEntry = obj.inner.mEntry;
+
+        SimpleObject res = (SimpleObject)marshalUnmarshal(obj, marsh);
+
+        assertEquals(obj, res);
+
+        assertTrue(res.bArr == res.inner.bArr);
+        assertTrue(res.cArr == res.inner.cArr);
+        assertTrue(res.boolArr == res.inner.boolArr);
+        assertTrue(res.sArr == res.inner.sArr);
+        assertTrue(res.strArr == res.inner.strArr);
+        assertTrue(res.iArr == res.inner.iArr);
+        assertTrue(res.lArr == res.inner.lArr);
+        assertTrue(res.fArr == res.inner.fArr);
+        assertTrue(res.dArr == res.inner.dArr);
+        assertTrue(res.dateArr == res.inner.dateArr);
+        assertTrue(res.uuidArr == res.inner.uuidArr);
+        assertTrue(res.objArr == res.inner.objArr);
+        assertTrue(res.bdArr == res.inner.bdArr);
+        assertTrue(res.map == res.inner.map);
+        assertTrue(res.col == res.inner.col);
+        assertTrue(res.mEntry == res.inner.mEntry);
+    }
+
+    /**
      *
      */
     private static class ObjectWithClassFields {
@@ -2424,6 +2473,7 @@ public class GridPortableMarshallerSelfTest extends GridCommonAbstractTest {
         inner.map = new HashMap<>();
         inner.enumVal = TestEnum.A;
         inner.enumArr = new TestEnum[] {TestEnum.A, TestEnum.B};
+        inner.bdArr = new BigDecimal[] {new BigDecimal(1000), BigDecimal.ONE};
 
         inner.col.add("str1");
         inner.col.add("str2");
@@ -2433,6 +2483,8 @@ public class GridPortableMarshallerSelfTest extends GridCommonAbstractTest {
         inner.map.put(2, "str2");
         inner.map.put(3, "str3");
 
+        inner.mEntry = inner.map.entrySet().iterator().next();
+
         SimpleObject outer = new SimpleObject();
 
         outer.b = 2;
@@ -2464,6 +2516,8 @@ public class GridPortableMarshallerSelfTest extends GridCommonAbstractTest {
         outer.enumVal = TestEnum.B;
         outer.enumArr = new TestEnum[] {TestEnum.B, TestEnum.C};
         outer.inner = inner;
+        outer.bdArr = new BigDecimal[] {new BigDecimal(5000), BigDecimal.TEN};
+
 
         outer.col.add("str4");
         outer.col.add("str5");
@@ -2473,6 +2527,8 @@ public class GridPortableMarshallerSelfTest extends GridCommonAbstractTest {
         outer.map.put(5, "str5");
         outer.map.put(6, "str6");
 
+        outer.mEntry = outer.map.entrySet().iterator().next();
+
         return outer;
     }
 
@@ -2757,6 +2813,9 @@ public class GridPortableMarshallerSelfTest extends GridCommonAbstractTest {
         private Object[] objArr;
 
         /** */
+        private BigDecimal[] bdArr;
+
+        /** */
         private Collection<String> col;
 
         /** */
@@ -2769,6 +2828,9 @@ public class GridPortableMarshallerSelfTest extends GridCommonAbstractTest {
         private TestEnum[] enumArr;
 
         /** */
+        private Map.Entry<Integer, String> mEntry;
+
+        /** */
         private SimpleObject inner;
 
         /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableMetaDataDisabledSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableMetaDataDisabledSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableMetaDataDisabledSelfTest.java
index d329818..05df23b 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableMetaDataDisabledSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableMetaDataDisabledSelfTest.java
@@ -20,6 +20,7 @@ import java.util.Arrays;
 import org.apache.ignite.IgnitePortables;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.marshaller.portable.PortableMarshaller;
+import org.apache.ignite.portable.PortableBuilder;
 import org.apache.ignite.portable.PortableException;
 import org.apache.ignite.portable.PortableMarshalAware;
 import org.apache.ignite.portable.PortableReader;
@@ -68,9 +69,17 @@ public class GridPortableMetaDataDisabledSelfTest extends GridCommonAbstractTest
 
             portables().toPortable(new TestObject1());
             portables().toPortable(new TestObject2());
+            portables().toPortable(new TestObject3());
 
             assertEquals(0, portables().metadata(TestObject1.class).fields().size());
             assertEquals(0, portables().metadata(TestObject2.class).fields().size());
+
+            PortableBuilder bldr = portables().builder("FakeType");
+
+            bldr.setField("field1", 0).setField("field2", "value").build();
+
+            assertNull(portables().metadata("FakeType"));
+            assertNull(portables().metadata(TestObject3.class));
         }
         finally {
             stopGrid();
@@ -218,4 +227,12 @@ public class GridPortableMetaDataDisabledSelfTest extends GridCommonAbstractTest
             // No-op.
         }
     }
+
+    /**
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class TestObject3 {
+        /** */
+        private int field;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableMetaDataSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableMetaDataSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableMetaDataSelfTest.java
index f6d7627..9054297 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableMetaDataSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/GridPortableMetaDataSelfTest.java
@@ -147,6 +147,15 @@ public class GridPortableMetaDataSelfTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    public void testNoConfiguration() throws Exception {
+        portables().toPortable(new TestObject3());
+
+        assertNotNull(portables().metadata(TestObject3.class));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
     public void testReflection() throws Exception {
         PortableMetadata meta = portables().metadata(TestObject1.class);
 
@@ -349,4 +358,12 @@ public class GridPortableMetaDataSelfTest extends GridCommonAbstractTest {
             // No-op.
         }
     }
+
+    /**
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    private static class TestObject3 {
+        /** */
+        private int intVal;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/test/java/org/apache/ignite/internal/portable/mutabletest/GridPortableTestClasses.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/mutabletest/GridPortableTestClasses.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/mutabletest/GridPortableTestClasses.java
index ce97a8d..e49514b 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/portable/mutabletest/GridPortableTestClasses.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/mutabletest/GridPortableTestClasses.java
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.io.ObjectOutput;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
@@ -182,7 +183,6 @@ public class GridPortableTestClasses {
         /** */
         public Date date;
 
-
         /** */
         public byte[] bArr;
 
@@ -208,12 +208,18 @@ public class GridPortableTestClasses {
         public boolean[] zArr;
 
         /** */
+        public BigDecimal[] bdArr;
+
+        /** */
         public String[] strArr;
 
         /** */
         public UUID[] uuidArr;
 
         /** */
+        public Date[] dateArr;
+
+        /** */
         public TestObjectEnum anEnum;
 
         /** */
@@ -222,8 +228,6 @@ public class GridPortableTestClasses {
         /** */
         public Map.Entry entry;
 
-        //public Date[] dateArr; // todo test date array.
-
         /**
          * @return Array.
          */
@@ -270,21 +274,23 @@ public class GridPortableTestClasses {
             uuid = new UUID(1, 1);
             date = new Date(1000000);
 
-            bArr = new byte[]{1, 2, 3};
-            sArr = new short[]{1, 2, 3};
-            iArr = new int[]{1, 2, 3};
-            lArr = new long[]{1, 2, 3};
-            fArr = new float[]{1, 2, 3};
-            dArr = new double[]{1, 2, 3};
-            cArr = new char[]{1, 2, 3};
-            zArr = new boolean[]{true, false};
+            bArr = new byte[] {1, 2, 3};
+            sArr = new short[] {1, 2, 3};
+            iArr = new int[] {1, 2, 3};
+            lArr = new long[] {1, 2, 3};
+            fArr = new float[] {1, 2, 3};
+            dArr = new double[] {1, 2, 3};
+            cArr = new char[] {1, 2, 3};
+            zArr = new boolean[] {true, false};
 
-            strArr = new String[]{"abc", "ab", "a"};
-            uuidArr = new UUID[]{new UUID(1, 1), new UUID(2, 2)};
+            strArr = new String[] {"abc", "ab", "a"};
+            uuidArr = new UUID[] {new UUID(1, 1), new UUID(2, 2)};
+            bdArr = new BigDecimal[] {new BigDecimal(1000), BigDecimal.TEN};
+            dateArr = new Date[] {new Date(1000000), new Date(200000)};
 
             anEnum = TestObjectEnum.A;
 
-            enumArr = new TestObjectEnum[]{TestObjectEnum.B};
+            enumArr = new TestObjectEnum[] {TestObjectEnum.B};
 
             entry = new GridMapEntry<>(1, "a");
         }
@@ -388,7 +394,6 @@ public class GridPortableTestClasses {
         private Map<String, List<Company>> companyByStreet = new TreeMap<>();
 
         /**
-         *
          * @param street Street.
          * @return Company.
          */
@@ -397,7 +402,6 @@ public class GridPortableTestClasses {
         }
 
         /**
-         *
          * @param company Company.
          */
         public void addCompany(Company company) {
@@ -413,7 +417,6 @@ public class GridPortableTestClasses {
         }
 
         /**
-         *
          * @return map
          */
         public Map<String, List<Company>> getCompanyByStreet() {
@@ -421,7 +424,6 @@ public class GridPortableTestClasses {
         }
 
         /**
-         *
          * @param companyByStreet map
          */
         public void setCompanyByStreet(Map<String, List<Company>> companyByStreet) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/portable/GridCacheClientNodePortableMetadataMultinodeTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/portable/GridCacheClientNodePortableMetadataMultinodeTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/portable/GridCacheClientNodePortableMetadataMultinodeTest.java
index aa67574..1ba3d4d 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/portable/GridCacheClientNodePortableMetadataMultinodeTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/portable/GridCacheClientNodePortableMetadataMultinodeTest.java
@@ -31,6 +31,7 @@ import org.apache.ignite.IgnitePortables;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.util.lang.GridAbsPredicate;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.marshaller.portable.PortableMarshaller;
 import org.apache.ignite.portable.PortableBuilder;
@@ -233,6 +234,16 @@ public class GridCacheClientNodePortableMetadataMultinodeTest extends GridCommon
 
             portables = ignite(i).portables();
 
+            final IgnitePortables p0 = portables;
+
+            GridTestUtils.waitForCondition(new GridAbsPredicate() {
+                @Override public boolean apply() {
+                    Collection<PortableMetadata> metaCol = p0.metadata();
+
+                    return metaCol.size() == 1000;
+                }
+            }, getTestTimeout());
+
             Collection<PortableMetadata> metaCol = portables.metadata();
 
             assertEquals(1000, metaCol.size());


[2/4] ignite git commit: ignite-1273: fixed cyclic references processing by PortableMarshaller and ability to modify array fields returned by PortableBuilder

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderReader.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderReader.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderReader.java
new file mode 100644
index 0000000..45355d7
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderReader.java
@@ -0,0 +1,800 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.ignite.internal.portable.GridPortableMarshaller;
+import org.apache.ignite.internal.portable.PortableContext;
+import org.apache.ignite.internal.portable.PortableObjectImpl;
+import org.apache.ignite.internal.portable.PortablePrimitives;
+import org.apache.ignite.internal.portable.PortableReaderExImpl;
+import org.apache.ignite.internal.portable.PortableUtils;
+import org.apache.ignite.internal.portable.PortableWriterExImpl;
+import org.apache.ignite.portable.PortableException;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.ignite.internal.portable.GridPortableMarshaller.NULL;
+import static org.apache.ignite.internal.portable.GridPortableMarshaller.STRING;
+
+/**
+ *
+ */
+class PortableBuilderReader {
+    /** */
+    private static final PortablePrimitives PRIM = PortablePrimitives.get();
+
+    /** */
+    private final Map<Integer, PortableBuilderImpl> objMap = new HashMap<>();
+
+    /** */
+    private final PortableContext ctx;
+
+    /** */
+    private final PortableReaderExImpl reader;
+
+    /** */
+    private byte[] arr;
+
+    /** */
+    private int pos;
+
+    /**
+     * @param objImpl Portable object
+     */
+    PortableBuilderReader(PortableObjectImpl objImpl) {
+        ctx = objImpl.context();
+        arr = objImpl.array();
+        pos = objImpl.start();
+
+        // TODO: IGNITE-1272 - Is class loader needed here?
+        reader = new PortableReaderExImpl(portableContext(), arr, pos, null);
+    }
+
+    /**
+     * @return Portable context.
+     */
+    public PortableContext portableContext() {
+        return ctx;
+    }
+
+    /**
+     * @param obj Mutable portable object.
+     */
+    public void registerObject(PortableBuilderImpl obj) {
+        objMap.put(obj.start(), obj);
+    }
+
+    /**
+     * @return Read int value.
+     */
+    public int readInt() {
+        int res = readInt(0);
+
+        pos += 4;
+
+        return res;
+    }
+
+    /**
+     * @return Read int value.
+     */
+    public byte readByte() {
+        return arr[pos++];
+    }
+
+    /**
+     * @return Read boolean value.
+     */
+    public boolean readBoolean() {
+        return readByte() == 1;
+    }
+
+    /**
+     * @return Read int value.
+     */
+    public byte readByte(int off) {
+        return arr[pos + off];
+    }
+
+    /**
+     * @param off Offset related to {@link #pos}
+     * @return Read int value.
+     */
+    public int readInt(int off) {
+        return PRIM.readInt(arr, pos + off);
+    }
+
+    /**
+     * @param pos Position in the source array.
+     * @return Read int value.
+     */
+    public int readIntAbsolute(int pos) {
+        return PRIM.readInt(arr, pos);
+    }
+
+    /**
+     * @return Read length of array.
+     */
+    public int readLength() {
+        return PRIM.readInt(arr, pos);
+    }
+
+    /**
+     * Read string length.
+     *
+     * @return String length.
+     */
+    public int readStringLength() {
+        boolean utf = PRIM.readBoolean(arr, pos);
+
+        int arrLen = PRIM.readInt(arr, pos + 1);
+
+        return 1 + (utf ? arrLen : arrLen << 1);
+    }
+
+    /**
+     * Reads string.
+     *
+     * @return String.
+     */
+    public String readString() {
+        byte flag = readByte();
+
+        if (flag == NULL)
+            return null;
+
+        if (flag != STRING)
+            throw new PortableException("Failed to deserialize String.");
+
+        boolean convert = readBoolean();
+        int len = readInt();
+
+        String str;
+
+        if (convert) {
+            str = new String(arr, pos, len, UTF_8);
+
+            pos += len;
+        }
+        else {
+            str = String.valueOf(PRIM.readCharArray(arr, pos, len));
+
+            pos += len << 1;
+        }
+
+        return str;
+    }
+
+    /**
+     *
+     */
+    public void skipValue() {
+        byte type = arr[pos++];
+
+        int len;
+
+        switch (type) {
+            case GridPortableMarshaller.NULL:
+                return;
+
+            case GridPortableMarshaller.OBJ:
+                pos += readInt(GridPortableMarshaller.TOTAL_LEN_POS - 1) - 1;
+
+                return;
+
+            case GridPortableMarshaller.BOOLEAN:
+            case GridPortableMarshaller.BYTE:
+                len = 1;
+                break;
+
+            case GridPortableMarshaller.CHAR:
+            case GridPortableMarshaller.SHORT:
+                len = 2;
+
+                break;
+
+            case GridPortableMarshaller.HANDLE:
+            case GridPortableMarshaller.FLOAT:
+            case GridPortableMarshaller.INT:
+                len = 4;
+
+                break;
+
+            case GridPortableMarshaller.ENUM:
+                //skipping type id and ordinal value
+                len = 8;
+
+                break;
+
+            case GridPortableMarshaller.LONG:
+            case GridPortableMarshaller.DOUBLE:
+                len = 8;
+
+                break;
+
+            case GridPortableMarshaller.BYTE_ARR:
+            case GridPortableMarshaller.BOOLEAN_ARR:
+                len = 4 + readLength();
+
+                break;
+
+            case GridPortableMarshaller.STRING:
+                len = 4 + readStringLength();
+
+                break;
+
+            case GridPortableMarshaller.DECIMAL:
+                len = /** scale */ 4  + /** mag len */ 4  + /** mag bytes count */ readInt(4);
+
+                break;
+
+            case GridPortableMarshaller.UUID:
+                len = 8 + 8;
+
+                break;
+
+            case GridPortableMarshaller.DATE:
+                len = 8 + 4;
+
+                break;
+
+            case GridPortableMarshaller.CHAR_ARR:
+            case GridPortableMarshaller.SHORT_ARR:
+                len = 4 + readLength() * 2;
+
+                break;
+
+            case GridPortableMarshaller.INT_ARR:
+            case GridPortableMarshaller.FLOAT_ARR:
+                len = 4 + readLength() * 4;
+
+                break;
+
+            case GridPortableMarshaller.LONG_ARR:
+            case GridPortableMarshaller.DOUBLE_ARR:
+                len = 4 + readLength() * 8;
+
+                break;
+
+            case GridPortableMarshaller.DECIMAL_ARR:
+            case GridPortableMarshaller.DATE_ARR:
+            case GridPortableMarshaller.OBJ_ARR:
+            case GridPortableMarshaller.ENUM_ARR:
+            case GridPortableMarshaller.UUID_ARR:
+            case GridPortableMarshaller.STRING_ARR: {
+                int size = readInt();
+
+                for (int i = 0; i < size; i++)
+                    skipValue();
+
+                return;
+            }
+
+            case GridPortableMarshaller.COL: {
+                int size = readInt();
+
+                pos++; // skip collection type
+
+                for (int i = 0; i < size; i++)
+                    skipValue();
+
+                return;
+            }
+
+            case GridPortableMarshaller.MAP: {
+                int size = readInt();
+
+                pos++; // skip collection type
+
+                for (int i = 0; i < size; i++) {
+                    skipValue(); // skip key.
+                    skipValue(); // skip value.
+                }
+
+                return;
+            }
+
+            case GridPortableMarshaller.MAP_ENTRY:
+                skipValue();
+                skipValue();
+
+                return;
+
+            case GridPortableMarshaller.PORTABLE_OBJ:
+                len = readInt() + 4;
+
+                break;
+
+            default:
+                throw new PortableException("Invalid flag value: " + type);
+        }
+
+        pos += len;
+    }
+
+    /**
+     * @param pos Position.
+     * @param len Length.
+     * @return Object.
+     */
+    public Object getValueQuickly(int pos, int len) {
+        byte type = arr[pos];
+
+        switch (type) {
+            case GridPortableMarshaller.NULL:
+                return null;
+
+            case GridPortableMarshaller.HANDLE: {
+                int objStart = pos - readIntAbsolute(pos + 1);
+
+                PortableBuilderImpl res = objMap.get(objStart);
+
+                if (res == null) {
+                    res = new PortableBuilderImpl(this, objStart);
+
+                    objMap.put(objStart, res);
+                }
+
+                return res;
+            }
+
+            case GridPortableMarshaller.OBJ: {
+                PortableBuilderImpl res = objMap.get(pos);
+
+                if (res == null) {
+                    res = new PortableBuilderImpl(this, pos);
+
+                    objMap.put(pos, res);
+                }
+
+                return res;
+            }
+
+            case GridPortableMarshaller.BYTE:
+                return arr[pos + 1];
+
+            case GridPortableMarshaller.SHORT:
+                return PRIM.readShort(arr, pos + 1);
+
+            case GridPortableMarshaller.INT:
+                return PRIM.readInt(arr, pos + 1);
+
+            case GridPortableMarshaller.LONG:
+                return PRIM.readLong(arr, pos + 1);
+
+            case GridPortableMarshaller.FLOAT:
+                return PRIM.readFloat(arr, pos + 1);
+
+            case GridPortableMarshaller.DOUBLE:
+                return PRIM.readDouble(arr, pos + 1);
+
+            case GridPortableMarshaller.CHAR:
+                return PRIM.readChar(arr, pos + 1);
+
+            case GridPortableMarshaller.BOOLEAN:
+                return arr[pos + 1] != 0;
+
+            case GridPortableMarshaller.DECIMAL:
+            case GridPortableMarshaller.STRING:
+            case GridPortableMarshaller.UUID:
+            case GridPortableMarshaller.DATE:
+                return new PortablePlainLazyValue(this, pos, len);
+
+            case GridPortableMarshaller.BYTE_ARR:
+            case GridPortableMarshaller.SHORT_ARR:
+            case GridPortableMarshaller.INT_ARR:
+            case GridPortableMarshaller.LONG_ARR:
+            case GridPortableMarshaller.FLOAT_ARR:
+            case GridPortableMarshaller.DOUBLE_ARR:
+            case GridPortableMarshaller.CHAR_ARR:
+            case GridPortableMarshaller.BOOLEAN_ARR:
+            case GridPortableMarshaller.DECIMAL_ARR:
+            case GridPortableMarshaller.DATE_ARR:
+            case GridPortableMarshaller.UUID_ARR:
+            case GridPortableMarshaller.STRING_ARR:
+            case GridPortableMarshaller.ENUM_ARR:
+            case GridPortableMarshaller.OBJ_ARR:
+            case GridPortableMarshaller.COL:
+            case GridPortableMarshaller.MAP:
+            case GridPortableMarshaller.MAP_ENTRY:
+                return new LazyCollection(pos);
+
+            case GridPortableMarshaller.ENUM: {
+                if (len == 1) {
+                    assert readByte(pos) == GridPortableMarshaller.NULL;
+
+                    return null;
+                }
+
+                int mark = position();
+                position(pos + 1);
+
+                PortableBuilderEnum builderEnum = new PortableBuilderEnum(this);
+
+                position(mark);
+
+                return builderEnum;
+            }
+
+            case GridPortableMarshaller.PORTABLE_OBJ: {
+                int size = readIntAbsolute(pos + 1);
+
+                int start = readIntAbsolute(pos + 4 + size);
+
+                PortableObjectImpl portableObj = new PortableObjectImpl(ctx, arr, pos + 4 + start);
+
+                return new PortablePlainPortableObject(portableObj);
+            }
+
+            default:
+                throw new PortableException("Invalid flag value: " + type);
+        }
+    }
+
+    /**
+     * @return Parsed value.
+     */
+    public Object parseValue() {
+        int valPos = pos;
+
+        byte type = arr[pos++];
+
+        int plainLazyValLen;
+
+        boolean modifiableLazyVal = false;
+
+        switch (type) {
+            case GridPortableMarshaller.NULL:
+                return null;
+
+            case GridPortableMarshaller.HANDLE: {
+                int objStart = pos - 1 - readInt();
+
+                PortableBuilderImpl res = objMap.get(objStart);
+
+                if (res == null) {
+                    res = new PortableBuilderImpl(this, objStart);
+
+                    objMap.put(objStart, res);
+                }
+
+                return res;
+            }
+
+            case GridPortableMarshaller.OBJ: {
+                pos--;
+
+                PortableBuilderImpl res = objMap.get(pos);
+
+                if (res == null) {
+                    res = new PortableBuilderImpl(this, pos);
+
+                    objMap.put(pos, res);
+                }
+
+                pos += readInt(GridPortableMarshaller.TOTAL_LEN_POS);
+
+                return res;
+            }
+
+            case GridPortableMarshaller.BYTE:
+                return arr[pos++];
+
+            case GridPortableMarshaller.SHORT: {
+                Object res = PRIM.readShort(arr, pos);
+                pos += 2;
+                return res;
+            }
+
+            case GridPortableMarshaller.INT:
+                return readInt();
+
+            case GridPortableMarshaller.LONG:
+                plainLazyValLen = 8;
+
+                break;
+
+            case GridPortableMarshaller.FLOAT:
+                plainLazyValLen = 4;
+
+                break;
+
+            case GridPortableMarshaller.DOUBLE:
+                plainLazyValLen = 8;
+
+                break;
+
+            case GridPortableMarshaller.CHAR:
+                plainLazyValLen = 2;
+
+                break;
+
+            case GridPortableMarshaller.BOOLEAN:
+                return arr[pos++] != 0;
+
+            case GridPortableMarshaller.DECIMAL:
+                plainLazyValLen = /** scale */ 4  + /** mag len */ 4  + /** mag bytes count */ readInt(4);
+
+                break;
+
+            case GridPortableMarshaller.STRING:
+                plainLazyValLen = 4 + readStringLength();
+
+                break;
+
+            case GridPortableMarshaller.UUID:
+                plainLazyValLen = 8 + 8;
+
+                break;
+
+            case GridPortableMarshaller.DATE:
+                plainLazyValLen = 8 + 4;
+
+                break;
+
+            case GridPortableMarshaller.BYTE_ARR:
+                plainLazyValLen = 4 + readLength();
+                modifiableLazyVal = true;
+
+                break;
+
+            case GridPortableMarshaller.SHORT_ARR:
+                plainLazyValLen = 4 + readLength() * 2;
+                modifiableLazyVal = true;
+
+                break;
+
+            case GridPortableMarshaller.INT_ARR:
+                plainLazyValLen = 4 + readLength() * 4;
+                modifiableLazyVal = true;
+
+                break;
+
+            case GridPortableMarshaller.LONG_ARR:
+                plainLazyValLen = 4 + readLength() * 8;
+                modifiableLazyVal = true;
+
+                break;
+
+            case GridPortableMarshaller.FLOAT_ARR:
+                plainLazyValLen = 4 + readLength() * 4;
+                modifiableLazyVal = true;
+
+                break;
+
+            case GridPortableMarshaller.DOUBLE_ARR:
+                plainLazyValLen = 4 + readLength() * 8;
+                modifiableLazyVal = true;
+
+                break;
+
+            case GridPortableMarshaller.CHAR_ARR:
+                plainLazyValLen = 4 + readLength() * 2;
+                modifiableLazyVal = true;
+
+                break;
+
+            case GridPortableMarshaller.BOOLEAN_ARR:
+                plainLazyValLen = 4 + readLength();
+                modifiableLazyVal = true;
+
+                break;
+
+            case GridPortableMarshaller.OBJ_ARR:
+                return new PortableObjectArrayLazyValue(this);
+
+            case GridPortableMarshaller.DATE_ARR: {
+                int size = readInt();
+
+                Date[] res = new Date[size];
+
+                for (int i = 0; i < res.length; i++) {
+                    byte flag = arr[pos++];
+
+                    if (flag == GridPortableMarshaller.NULL) continue;
+
+                    if (flag != GridPortableMarshaller.DATE)
+                        throw new PortableException("Invalid flag value: " + flag);
+
+                    long time = PRIM.readLong(arr, pos);
+
+                    pos += 8;
+
+                    if (ctx.isUseTimestamp()) {
+                        Timestamp ts = new Timestamp(time);
+
+                        ts.setNanos(ts.getNanos() + readInt());
+
+                        res[i] = ts;
+                    }
+                    else {
+                        res[i] = new Date(time);
+
+                        pos += 4;
+                    }
+                }
+
+                return res;
+            }
+
+            case GridPortableMarshaller.UUID_ARR:
+            case GridPortableMarshaller.STRING_ARR:
+            case GridPortableMarshaller.DECIMAL_ARR: {
+                int size = readInt();
+
+                for (int i = 0; i < size; i++) {
+                    byte flag = arr[pos++];
+
+                    if (flag == GridPortableMarshaller.UUID)
+                        pos += 8 + 8;
+                    else if (flag == GridPortableMarshaller.STRING)
+                        pos += 4 + readStringLength();
+                    else if (flag == GridPortableMarshaller.DECIMAL) {
+                        pos += 4; // scale value
+                        pos += 4 + readLength();
+                    }
+                    else
+                        assert flag == GridPortableMarshaller.NULL;
+                }
+
+                return new PortableModifiableLazyValue(this, valPos, pos - valPos);
+            }
+
+            case GridPortableMarshaller.COL: {
+                int size = readInt();
+                byte colType = arr[pos++];
+
+                switch (colType) {
+                    case GridPortableMarshaller.USER_COL:
+                    case GridPortableMarshaller.ARR_LIST:
+                        return new PortableLazyArrayList(this, size);
+
+                    case GridPortableMarshaller.LINKED_LIST:
+                        return new PortableLazyLinkedList(this, size);
+
+                    case GridPortableMarshaller.HASH_SET:
+                    case GridPortableMarshaller.LINKED_HASH_SET:
+                    case GridPortableMarshaller.TREE_SET:
+                    case GridPortableMarshaller.CONC_SKIP_LIST_SET:
+                        return new PortableLazySet(this, size);
+                }
+
+                throw new PortableException("Unknown collection type: " + colType);
+            }
+
+            case GridPortableMarshaller.MAP:
+                return PortableLazyMap.parseMap(this);
+
+            case GridPortableMarshaller.ENUM:
+                return new PortableBuilderEnum(this);
+
+            case GridPortableMarshaller.ENUM_ARR:
+                return new PortableEnumArrayLazyValue(this);
+
+            case GridPortableMarshaller.MAP_ENTRY:
+                return new PortableLazyMapEntry(this);
+
+            case GridPortableMarshaller.PORTABLE_OBJ: {
+                int size = readInt();
+
+                pos += size;
+
+                int start = readInt();
+
+                PortableObjectImpl portableObj = new PortableObjectImpl(ctx, arr,
+                    pos - 4 - size + start);
+
+                return new PortablePlainPortableObject(portableObj);
+            }
+
+
+            default:
+                throw new PortableException("Invalid flag value: " + type);
+        }
+
+        PortableAbstractLazyValue res;
+
+        if (modifiableLazyVal)
+            res = new PortableModifiableLazyValue(this, valPos, 1 + plainLazyValLen);
+        else
+            res = new PortablePlainLazyValue(this, valPos, 1 + plainLazyValLen);
+
+        pos += plainLazyValLen;
+
+        return res;
+    }
+
+    /**
+     * @return Array.
+     */
+    public byte[] array() {
+        return arr;
+    }
+
+    /**
+     * @return Position of reader.
+     */
+    public int position() {
+        return pos;
+    }
+
+    /**
+     * @param pos New pos.
+     */
+    public void position(int pos) {
+        this.pos = pos;
+    }
+
+    /**
+     * @param n Number of bytes to skip.
+     */
+    public void skip(int n) {
+        pos += n;
+    }
+
+    /**
+     * @return Reader.
+     */
+    PortableReaderExImpl reader() {
+        return reader;
+    }
+
+    /**
+     *
+     */
+    private class LazyCollection implements PortableLazyValue {
+        /** */
+        private final int valOff;
+
+        /** */
+        private Object col;
+
+        /**
+         * @param valOff Value.
+         */
+        protected LazyCollection(int valOff) {
+            this.valOff = valOff;
+        }
+
+        /**
+         * @return Object.
+         */
+        private Object wrappedCollection() {
+            if (col == null) {
+                position(valOff);
+
+                col = parseValue();
+            }
+
+            return col;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
+            ctx.writeValue(writer, wrappedCollection());
+        }
+
+        /** {@inheritDoc} */
+        @Override public Object value() {
+            return PortableUtils.unwrapLazy(wrappedCollection());
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderSerializationAware.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderSerializationAware.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderSerializationAware.java
new file mode 100644
index 0000000..976059a
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderSerializationAware.java
@@ -0,0 +1,31 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+import org.apache.ignite.internal.portable.*;
+
+/**
+ *
+ */
+interface PortableBuilderSerializationAware {
+    /**
+     * @param writer Writer.
+     * @param ctx Context.
+     */
+    public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderSerializer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderSerializer.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderSerializer.java
new file mode 100644
index 0000000..2d9c961
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderSerializer.java
@@ -0,0 +1,214 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+import org.apache.ignite.internal.portable.GridPortableMarshaller;
+import org.apache.ignite.internal.portable.PortableObjectEx;
+import org.apache.ignite.internal.portable.PortableUtils;
+import org.apache.ignite.internal.portable.PortableWriterExImpl;
+import org.apache.ignite.internal.util.*;
+import org.apache.ignite.portable.*;
+
+import java.util.*;
+
+/**
+ *
+ */
+class PortableBuilderSerializer {
+    /** */
+    private final Map<PortableBuilderImpl, Integer> objToPos = new IdentityHashMap<>();
+
+    /** */
+    private Map<PortableObject, PortableBuilderImpl> portableObjToWrapper;
+
+    /**
+     * @param obj Mutable object.
+     * @param posInResArr Object position in the array.
+     */
+    public void registerObjectWriting(PortableBuilderImpl obj, int posInResArr) {
+        objToPos.put(obj, posInResArr);
+    }
+
+    /**
+     * @param writer Writer.
+     * @param val Value.
+     */
+    public void writeValue(PortableWriterExImpl writer, Object val) {
+        if (val == null) {
+            writer.writeByte(GridPortableMarshaller.NULL);
+
+            return;
+        }
+
+        if (val instanceof PortableBuilderSerializationAware) {
+            ((PortableBuilderSerializationAware)val).writeTo(writer, this);
+
+            return;
+        }
+
+        if (val instanceof PortableObjectEx) {
+            if (portableObjToWrapper == null)
+                portableObjToWrapper = new IdentityHashMap<>();
+
+            PortableBuilderImpl wrapper = portableObjToWrapper.get(val);
+
+            if (wrapper == null) {
+                wrapper = PortableBuilderImpl.wrap((PortableObject)val);
+
+                portableObjToWrapper.put((PortableObject)val, wrapper);
+            }
+
+            val = wrapper;
+        }
+
+        if (val instanceof PortableBuilderImpl) {
+            PortableBuilderImpl obj = (PortableBuilderImpl)val;
+
+            Integer posInResArr = objToPos.get(obj);
+
+            if (posInResArr == null) {
+                objToPos.put(obj, writer.outputStream().position());
+
+                obj.serializeTo(writer.newWriter(obj.typeId()), this);
+            }
+            else {
+                int handle = writer.outputStream().position() - posInResArr;
+
+                writer.writeByte(GridPortableMarshaller.HANDLE);
+                writer.writeInt(handle);
+            }
+
+            return;
+        }
+
+        if (val.getClass().isEnum()) {
+            writer.writeByte(GridPortableMarshaller.ENUM);
+            writer.writeInt(writer.context().typeId(val.getClass().getName()));
+            writer.writeInt(((Enum)val).ordinal());
+
+            return;
+        }
+
+        if (val instanceof Collection) {
+            Collection<?> c = (Collection<?>)val;
+
+            writer.writeByte(GridPortableMarshaller.COL);
+            writer.writeInt(c.size());
+
+            byte colType;
+
+            if (c instanceof GridConcurrentSkipListSet)
+                colType = GridPortableMarshaller.CONC_SKIP_LIST_SET;
+            else
+                colType = writer.context().collectionType(c.getClass());
+
+
+            writer.writeByte(colType);
+
+            for (Object obj : c)
+                writeValue(writer, obj);
+
+            return;
+        }
+
+        if (val instanceof Map) {
+            Map<?, ?> map = (Map<?, ?>)val;
+
+            writer.writeByte(GridPortableMarshaller.MAP);
+            writer.writeInt(map.size());
+
+            writer.writeByte(writer.context().mapType(map.getClass()));
+
+            for (Map.Entry<?, ?> entry : map.entrySet()) {
+                writeValue(writer, entry.getKey());
+                writeValue(writer, entry.getValue());
+            }
+
+            return;
+        }
+
+        Byte flag = PortableUtils.PLAIN_CLASS_TO_FLAG.get(val.getClass());
+
+        if (flag != null) {
+            PortableUtils.writePlainObject(writer, val);
+
+            return;
+        }
+
+        if (val instanceof Object[]) {
+            int compTypeId = writer.context().typeId(((Object[])val).getClass().getComponentType().getName());
+
+            if (val instanceof PortableBuilderEnum[]) {
+                writeArray(writer, GridPortableMarshaller.ENUM_ARR, (Object[])val, compTypeId);
+
+                return;
+            }
+
+            if (((Object[])val).getClass().getComponentType().isEnum()) {
+                Enum[] enumArr = (Enum[])val;
+
+                writer.writeByte(GridPortableMarshaller.ENUM_ARR);
+                writer.writeInt(compTypeId);
+                writer.writeInt(enumArr.length);
+
+                for (Enum anEnum : enumArr)
+                    writeValue(writer, anEnum);
+
+                return;
+            }
+
+            writeArray(writer, GridPortableMarshaller.OBJ_ARR, (Object[])val, compTypeId);
+
+            return;
+        }
+
+        writer.doWriteObject(val, false);
+    }
+
+    /**
+     * @param writer Writer.
+     * @param elementType Element type.
+     * @param arr The array.
+     * @param compTypeId Component type ID.
+     */
+    public void writeArray(PortableWriterExImpl writer, byte elementType, Object[] arr, int compTypeId) {
+        writer.writeByte(elementType);
+        writer.writeInt(compTypeId);
+        writer.writeInt(arr.length);
+
+        for (Object obj : arr)
+            writeValue(writer, obj);
+    }
+
+    /**
+     * @param writer Writer.
+     * @param elementType Element type.
+     * @param arr The array.
+     * @param clsName Component class name.
+     */
+    public void writeArray(PortableWriterExImpl writer, byte elementType, Object[] arr, String clsName) {
+        writer.writeByte(elementType);
+        writer.writeInt(GridPortableMarshaller.UNREGISTERED_TYPE_ID);
+        writer.writeString(clsName);
+        writer.writeInt(arr.length);
+
+        for (Object obj : arr)
+            writeValue(writer, obj);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableEnumArrayLazyValue.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableEnumArrayLazyValue.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableEnumArrayLazyValue.java
new file mode 100644
index 0000000..d864a6e
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableEnumArrayLazyValue.java
@@ -0,0 +1,114 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+import org.apache.ignite.internal.portable.GridPortableMarshaller;
+import org.apache.ignite.internal.portable.PortableWriterExImpl;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.portable.PortableException;
+import org.apache.ignite.portable.PortableInvalidClassException;
+
+/**
+ *
+ */
+class PortableEnumArrayLazyValue extends PortableAbstractLazyValue {
+    /** */
+    private final int len;
+
+    /** */
+    private final int compTypeId;
+
+    /** */
+    private final String clsName;
+
+    /**
+     * @param reader Reader.
+     */
+    protected PortableEnumArrayLazyValue(PortableBuilderReader reader) {
+        super(reader, reader.position() - 1);
+
+        int typeId = reader.readInt();
+
+        if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) {
+            clsName = reader.readString();
+
+            Class cls;
+
+            try {
+                // TODO: IGNITE-1272 - Is class loader needed here?
+                cls = U.forName(reader.readString(), null);
+            }
+            catch (ClassNotFoundException e) {
+                throw new PortableInvalidClassException("Failed to load the class: " + clsName, e);
+            }
+
+            compTypeId = reader.portableContext().descriptorForClass(cls).typeId();
+        }
+        else {
+            compTypeId = typeId;
+            clsName = null;
+        }
+
+        int size = reader.readInt();
+
+        for (int i = 0; i < size; i++)
+            reader.skipValue();
+
+        len = reader.position() - valOff;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Object init() {
+        reader.position(valOff + 1);
+
+        //skipping component type id
+        reader.readInt();
+
+        int size = reader.readInt();
+
+        PortableBuilderEnum[] res = new PortableBuilderEnum[size];
+
+        for (int i = 0; i < size; i++) {
+            byte flag = reader.readByte();
+
+            if (flag == GridPortableMarshaller.NULL)
+                continue;
+
+            if (flag != GridPortableMarshaller.ENUM)
+                throw new PortableException("Invalid flag value: " + flag);
+
+            res[i] = new PortableBuilderEnum(reader);
+        }
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
+        if (val != null) {
+            if (clsName != null)
+                ctx.writeArray(writer, GridPortableMarshaller.ENUM_ARR, (Object[])val, clsName);
+            else
+                ctx.writeArray(writer, GridPortableMarshaller.ENUM_ARR, (Object[])val, compTypeId);
+
+            return;
+        }
+
+        writer.write(reader.array(), valOff, len);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyArrayList.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyArrayList.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyArrayList.java
new file mode 100644
index 0000000..a08cfdd
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyArrayList.java
@@ -0,0 +1,166 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+import org.apache.ignite.internal.portable.*;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ *
+ */
+class PortableLazyArrayList extends AbstractList<Object> implements PortableBuilderSerializationAware {
+    /** */
+    private final PortableBuilderReader reader;
+
+    /** */
+    private final int off;
+
+    /** */
+    private List<Object> delegate;
+
+    /**
+     * @param reader Reader.
+     * @param size Size,
+     */
+    PortableLazyArrayList(PortableBuilderReader reader, int size) {
+        this.reader = reader;
+        off = reader.position() - 1/* flag */ - 4/* size */ - 1/* col type */;
+
+        assert size >= 0;
+
+        for (int i = 0; i < size; i++)
+            reader.skipValue();
+    }
+
+    /**
+     *
+     */
+    private void ensureDelegateInit() {
+        if (delegate == null) {
+            int size = reader.readIntAbsolute(off + 1);
+
+            reader.position(off + 1/* flag */ + 4/* size */ + 1/* col type */);
+
+            delegate = new ArrayList<>(size);
+
+            for (int i = 0; i < size; i++)
+                delegate.add(reader.parseValue());
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object get(int idx) {
+        ensureDelegateInit();
+
+        return PortableUtils.unwrapLazy(delegate.get(idx));
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean add(Object o) {
+        ensureDelegateInit();
+
+        return delegate.add(o);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void add(int idx, Object element) {
+        ensureDelegateInit();
+
+        delegate.add(idx, element);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object set(int idx, Object element) {
+        ensureDelegateInit();
+
+        return PortableUtils.unwrapLazy(delegate.set(idx, element));
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object remove(int idx) {
+        ensureDelegateInit();
+
+        return PortableUtils.unwrapLazy(delegate.remove(idx));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void clear() {
+        if (delegate == null)
+            delegate = new ArrayList<>();
+        else
+            delegate.clear();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean addAll(int idx, Collection<?> c) {
+        return delegate.addAll(idx, c);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void removeRange(int fromIdx, int toIdx) {
+        ensureDelegateInit();
+
+        delegate.subList(fromIdx, toIdx).clear();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int size() {
+        if (delegate == null)
+            return reader.readIntAbsolute(off + 1);
+
+        return delegate.size();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
+        if (delegate == null) {
+            int size = reader.readIntAbsolute(off + 1);
+
+            int hdrSize = 1 /* flag */ + 4 /* size */ + 1 /* col type */;
+
+            writer.write(reader.array(), off, hdrSize);
+
+            reader.position(off + hdrSize);
+
+            for (int i = 0; i < size; i++) {
+                Object o = reader.parseValue();
+
+                ctx.writeValue(writer, o);
+            }
+        }
+        else {
+            writer.writeByte(GridPortableMarshaller.COL);
+            writer.writeInt(delegate.size());
+
+            byte colType = reader.array()[off + 1 /* flag */ + 4 /* size */];
+            writer.writeByte(colType);
+
+            int oldPos = reader.position();
+
+            for (Object o : delegate)
+                ctx.writeValue(writer, o);
+
+            // PortableBuilderImpl might have been written. It could override reader's position.
+            reader.position(oldPos);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyLinkedList.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyLinkedList.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyLinkedList.java
new file mode 100644
index 0000000..f793d7a
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyLinkedList.java
@@ -0,0 +1,217 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+import org.apache.ignite.internal.portable.*;
+
+import java.util.AbstractList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ *
+ */
+class PortableLazyLinkedList extends AbstractList<Object> implements PortableBuilderSerializationAware {
+    /** */
+    private final PortableBuilderReader reader;
+
+    /** */
+    private final int off;
+
+    /** */
+    private List<Object> delegate;
+
+    /**
+     * @param reader Reader.
+     * @param size Size,
+     */
+    PortableLazyLinkedList(PortableBuilderReader reader, int size) {
+        this.reader = reader;
+        off = reader.position() - 1/* flag */ - 4/* size */ - 1/* col type */;
+
+        assert size >= 0;
+
+        for (int i = 0; i < size; i++)
+            reader.skipValue();
+    }
+
+    /**
+     *
+     */
+    private void ensureDelegateInit() {
+        if (delegate == null) {
+            int size = reader.readIntAbsolute(off + 1);
+
+            reader.position(off + 1/* flag */ + 4/* size */ + 1/* col type */);
+
+            delegate = new LinkedList<>();
+
+            for (int i = 0; i < size; i++)
+                delegate.add(reader.parseValue());
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object get(int idx) {
+        ensureDelegateInit();
+
+        return PortableUtils.unwrapLazy(delegate.get(idx));
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean add(Object o) {
+        ensureDelegateInit();
+
+        return delegate.add(o);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void add(int idx, Object element) {
+        ensureDelegateInit();
+
+        delegate.add(idx, element);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object set(int idx, Object element) {
+        ensureDelegateInit();
+
+        return PortableUtils.unwrapLazy(delegate.set(idx, element));
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object remove(int idx) {
+        ensureDelegateInit();
+
+        return PortableUtils.unwrapLazy(delegate.remove(idx));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void clear() {
+        if (delegate == null)
+            delegate = new LinkedList<>();
+        else
+            delegate.clear();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean addAll(int idx, Collection<?> c) {
+        ensureDelegateInit();
+
+        return delegate.addAll(idx, c);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void removeRange(int fromIdx, int toIdx) {
+        ensureDelegateInit();
+
+        delegate.subList(fromIdx, toIdx).clear();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int size() {
+        if (delegate == null)
+            return reader.readIntAbsolute(off + 1);
+
+        return delegate.size();
+    }
+
+    /** {@inheritDoc} */
+    @Override public ListIterator<Object> listIterator(final int idx) {
+        ensureDelegateInit();
+
+        return new ListIterator<Object>() {
+            /** */
+            private final ListIterator<Object> delegate = PortableLazyLinkedList.super.listIterator(idx);
+
+            @Override public boolean hasNext() {
+                return delegate.hasNext();
+            }
+
+            @Override public Object next() {
+                return PortableUtils.unwrapLazy(delegate.next());
+            }
+
+            @Override public boolean hasPrevious() {
+                return delegate.hasPrevious();
+            }
+
+            @Override public Object previous() {
+                return PortableUtils.unwrapLazy(delegate.previous());
+            }
+
+            @Override public int nextIndex() {
+                return delegate.nextIndex();
+            }
+
+            @Override public int previousIndex() {
+                return delegate.previousIndex();
+            }
+
+            @Override public void remove() {
+                delegate.remove();
+            }
+
+            @Override public void set(Object o) {
+                delegate.set(o);
+            }
+
+            @Override public void add(Object o) {
+                delegate.add(o);
+            }
+        };
+    }
+
+    /** {@inheritDoc} */
+    @Override public Iterator<Object> iterator() {
+        ensureDelegateInit();
+
+        return PortableUtils.unwrapLazyIterator(super.iterator());
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
+        if (delegate == null) {
+            int size = reader.readIntAbsolute(off + 1);
+
+            int hdrSize = 1 /* flag */ + 4 /* size */ + 1 /* col type */;
+            writer.write(reader.array(), off, hdrSize);
+
+            reader.position(off + hdrSize);
+
+            for (int i = 0; i < size; i++) {
+                Object o = reader.parseValue();
+
+                ctx.writeValue(writer, o);
+            }
+        }
+        else {
+            writer.writeByte(GridPortableMarshaller.COL);
+            writer.writeInt(delegate.size());
+
+            byte colType = reader.array()[off + 1 /* flag */ + 4 /* size */];
+            writer.writeByte(colType);
+
+            for (Object o : delegate)
+                ctx.writeValue(writer, o);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyMap.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyMap.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyMap.java
new file mode 100644
index 0000000..12cbfd6
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyMap.java
@@ -0,0 +1,220 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+import org.apache.ignite.internal.portable.*;
+
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ *
+ */
+class PortableLazyMap extends AbstractMap<Object, Object> implements PortableBuilderSerializationAware {
+    /** */
+    private final PortableBuilderReader reader;
+
+    /** */
+    private final int off;
+
+    /** */
+    private Map<Object, Object> delegate;
+
+    /**
+     * @param reader Reader.
+     * @param off Offset.
+     */
+    private PortableLazyMap(PortableBuilderReader reader, int off) {
+        this.reader = reader;
+        this.off = off;
+    }
+
+    /**
+     * @param reader Reader.
+     * @return PortableLazyMap.
+     */
+    @Nullable public static PortableLazyMap parseMap(PortableBuilderReader reader) {
+        int off = reader.position() - 1;
+
+        int size = reader.readInt();
+
+        reader.skip(1); // map type.
+
+        for (int i = 0; i < size; i++) {
+            reader.skipValue(); // skip key
+            reader.skipValue(); // skip value
+        }
+
+        return new PortableLazyMap(reader, off);
+    }
+
+    /**
+     *
+     */
+    private void ensureDelegateInit() {
+        if (delegate == null) {
+            int size = reader.readIntAbsolute(off + 1);
+
+            reader.position(off + 1/* flag */ + 4/* size */ + 1/* col type */);
+
+            delegate = new LinkedHashMap<>();
+
+            for (int i = 0; i < size; i++)
+                delegate.put(PortableUtils.unwrapLazy(reader.parseValue()), reader.parseValue());
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
+        if (delegate == null) {
+            int size = reader.readIntAbsolute(off + 1);
+
+            int hdrSize = 1 /* flag */ + 4 /* size */ + 1 /* col type */;
+            writer.write(reader.array(), off, hdrSize);
+
+            reader.position(off + hdrSize);
+
+            for (int i = 0; i < size; i++) {
+                ctx.writeValue(writer, reader.parseValue()); // key
+                ctx.writeValue(writer, reader.parseValue()); // value
+            }
+        }
+        else {
+            writer.writeByte(GridPortableMarshaller.MAP);
+            writer.writeInt(delegate.size());
+
+            byte colType = reader.array()[off + 1 /* flag */ + 4 /* size */];
+
+            writer.writeByte(colType);
+
+            for (Entry<Object, Object> entry : delegate.entrySet()) {
+                ctx.writeValue(writer, entry.getKey());
+                ctx.writeValue(writer, entry.getValue());
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public int size() {
+        if (delegate == null)
+            return reader.readIntAbsolute(off + 1);
+
+        return delegate.size();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean containsKey(Object key) {
+        ensureDelegateInit();
+
+        return delegate.containsKey(key);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean containsValue(Object val) {
+        return values().contains(val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set<Object> keySet() {
+        ensureDelegateInit();
+
+        return delegate.keySet();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void clear() {
+        if (delegate == null)
+            delegate = new LinkedHashMap<>();
+        else
+            delegate.clear();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object get(Object key) {
+        ensureDelegateInit();
+
+        return PortableUtils.unwrapLazy(delegate.get(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object put(Object key, Object val) {
+        ensureDelegateInit();
+
+        return PortableUtils.unwrapLazy(delegate.put(key, val));
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object remove(Object key) {
+        ensureDelegateInit();
+
+        return PortableUtils.unwrapLazy(delegate.remove(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set<Entry<Object, Object>> entrySet() {
+        ensureDelegateInit();
+
+        return new AbstractSet<Entry<Object, Object>>() {
+            @Override public boolean contains(Object o) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override public Iterator<Entry<Object, Object>> iterator() {
+                return new Iterator<Entry<Object, Object>>() {
+                    /** */
+                    private final Iterator<Entry<Object, Object>> itr = delegate.entrySet().iterator();
+
+                    @Override public boolean hasNext() {
+                        return itr.hasNext();
+                    }
+
+                    @Override public Entry<Object, Object> next() {
+                        Entry<Object, Object> res = itr.next();
+
+                        final Object val = res.getValue();
+
+                        if (val instanceof PortableLazyValue) {
+                            return new SimpleEntry<Object, Object>(res.getKey(), val) {
+                                private static final long serialVersionUID = 0L;
+
+                                @Override public Object getValue() {
+                                    return ((PortableLazyValue)val).value();
+                                }
+                            };
+                        }
+
+                        return res;
+                    }
+
+                    @Override public void remove() {
+                        itr.remove();
+                    }
+                };
+            }
+
+            @Override public int size() {
+                return delegate.size();
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyMapEntry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyMapEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyMapEntry.java
new file mode 100644
index 0000000..bd027f5
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyMapEntry.java
@@ -0,0 +1,68 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+import org.apache.ignite.internal.portable.*;
+
+import java.util.Map;
+
+/**
+ *
+ */
+class PortableLazyMapEntry implements Map.Entry<Object, Object>, PortableBuilderSerializationAware {
+    /** */
+    private final Object key;
+
+    /** */
+    private Object val;
+
+    /**
+     * @param reader GridMutablePortableReader
+     */
+    PortableLazyMapEntry(PortableBuilderReader reader) {
+        key = reader.parseValue();
+        val = reader.parseValue();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object getKey() {
+        return PortableUtils.unwrapLazy(key);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object getValue() {
+        return PortableUtils.unwrapLazy(val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object setValue(Object val) {
+        Object res = getValue();
+
+        this.val = val;
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
+        writer.writeByte(GridPortableMarshaller.MAP_ENTRY);
+
+        ctx.writeValue(writer, key);
+        ctx.writeValue(writer, val);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazySet.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazySet.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazySet.java
new file mode 100644
index 0000000..16772af
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazySet.java
@@ -0,0 +1,92 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+import java.util.Collection;
+import java.util.Set;
+import org.apache.ignite.internal.portable.GridPortableMarshaller;
+import org.apache.ignite.internal.portable.PortableUtils;
+import org.apache.ignite.internal.portable.PortableWriterExImpl;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+/**
+ *
+ */
+class PortableLazySet extends PortableAbstractLazyValue {
+    /** */
+    private final int off;
+
+    /**
+     * @param reader Reader.
+     * @param size Size.
+     */
+    PortableLazySet(PortableBuilderReader reader, int size) {
+        super(reader, reader.position() - 1);
+
+        off = reader.position() - 1/* flag */ - 4/* size */ - 1/* col type */;
+
+        assert size >= 0;
+
+        for (int i = 0; i < size; i++)
+            reader.skipValue();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
+        if (val == null) {
+            int size = reader.readIntAbsolute(off + 1);
+
+            int hdrSize = 1 /* flag */ + 4 /* size */ + 1 /* col type */;
+            writer.write(reader.array(), off, hdrSize);
+
+            reader.position(off + hdrSize);
+
+            for (int i = 0; i < size; i++) {
+                Object o = reader.parseValue();
+
+                ctx.writeValue(writer, o);
+            }
+        }
+        else {
+            Collection<Object> c = (Collection<Object>)val;
+
+            writer.writeByte(GridPortableMarshaller.COL);
+            writer.writeInt(c.size());
+
+            byte colType = reader.array()[off + 1 /* flag */ + 4 /* size */];
+            writer.writeByte(colType);
+
+            for (Object o : c)
+                ctx.writeValue(writer, o);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Object init() {
+        int size = reader.readIntAbsolute(off + 1);
+
+        reader.position(off + 1/* flag */ + 4/* size */ + 1/* col type */);
+
+        Set<Object> res = U.newLinkedHashSet(size);
+
+        for (int i = 0; i < size; i++)
+            res.add(PortableUtils.unwrapLazy(reader.parseValue()));
+
+        return res;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyValue.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyValue.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyValue.java
new file mode 100644
index 0000000..5d8d586
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableLazyValue.java
@@ -0,0 +1,28 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+/**
+ *
+ */
+public interface PortableLazyValue extends PortableBuilderSerializationAware {
+    /**
+     * @return Value.
+     */
+    public Object value();
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableModifiableLazyValue.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableModifiableLazyValue.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableModifiableLazyValue.java
new file mode 100644
index 0000000..09fb844
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableModifiableLazyValue.java
@@ -0,0 +1,52 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+import org.apache.ignite.internal.portable.*;
+
+/**
+ *
+ */
+public class PortableModifiableLazyValue extends PortableAbstractLazyValue {
+    /** */
+    protected final int len;
+
+    /**
+     * @param reader
+     * @param valOff
+     * @param len
+     */
+    public PortableModifiableLazyValue(PortableBuilderReader reader, int valOff, int len) {
+        super(reader, valOff);
+
+        this.len = len;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Object init() {
+        return reader.reader().unmarshal(valOff);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
+        if (val == null)
+            writer.write(reader.array(), valOff, len);
+        else
+            writer.writeObject(val);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableObjectArrayLazyValue.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableObjectArrayLazyValue.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableObjectArrayLazyValue.java
new file mode 100644
index 0000000..1126a3c
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableObjectArrayLazyValue.java
@@ -0,0 +1,91 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+import org.apache.ignite.internal.portable.GridPortableMarshaller;
+import org.apache.ignite.internal.portable.PortableWriterExImpl;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.portable.PortableInvalidClassException;
+
+/**
+ *
+ */
+class PortableObjectArrayLazyValue extends PortableAbstractLazyValue {
+    /** */
+    private Object[] lazyValsArr;
+
+    /** */
+    private int compTypeId;
+
+    /** */
+    private String clsName;
+
+    /**
+     * @param reader Reader.
+     */
+    protected PortableObjectArrayLazyValue(PortableBuilderReader reader) {
+        super(reader, reader.position() - 1);
+
+        int typeId = reader.readInt();
+
+        if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) {
+            clsName = reader.readString();
+
+            Class cls;
+
+            try {
+                // TODO: IGNITE-1272 - Is class loader needed here?
+                cls = U.forName(reader.readString(), null);
+            }
+            catch (ClassNotFoundException e) {
+                throw new PortableInvalidClassException("Failed to load the class: " + clsName, e);
+            }
+
+            compTypeId = reader.portableContext().descriptorForClass(cls).typeId();
+        }
+        else {
+            compTypeId = typeId;
+            clsName = null;
+        }
+
+        int size = reader.readInt();
+
+        lazyValsArr = new Object[size];
+
+        for (int i = 0; i < size; i++)
+            lazyValsArr[i] = reader.parseValue();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Object init() {
+        for (int i = 0; i < lazyValsArr.length; i++) {
+            if (lazyValsArr[i] instanceof PortableLazyValue)
+                lazyValsArr[i] = ((PortableLazyValue)lazyValsArr[i]).value();
+        }
+
+        return lazyValsArr;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
+        if (clsName == null)
+            ctx.writeArray(writer, GridPortableMarshaller.OBJ_ARR, lazyValsArr, compTypeId);
+        else
+            ctx.writeArray(writer, GridPortableMarshaller.OBJ_ARR, lazyValsArr, clsName);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortablePlainLazyValue.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortablePlainLazyValue.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortablePlainLazyValue.java
new file mode 100644
index 0000000..136958a
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortablePlainLazyValue.java
@@ -0,0 +1,49 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+import org.apache.ignite.internal.portable.*;
+
+/**
+ *
+ */
+class PortablePlainLazyValue extends PortableAbstractLazyValue {
+    /** */
+    protected final int len;
+
+    /**
+     * @param reader Reader
+     * @param valOff Offset
+     * @param len Length.
+     */
+    protected PortablePlainLazyValue(PortableBuilderReader reader, int valOff, int len) {
+        super(reader, valOff);
+
+        this.len = len;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Object init() {
+        return reader.reader().unmarshal(valOff);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
+        writer.write(reader.array(), valOff, len);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortablePlainPortableObject.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortablePlainPortableObject.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortablePlainPortableObject.java
new file mode 100644
index 0000000..8743fbe
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortablePlainPortableObject.java
@@ -0,0 +1,53 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+import org.apache.ignite.internal.portable.PortableObjectImpl;
+import org.apache.ignite.internal.portable.PortableObjectOffheapImpl;
+import org.apache.ignite.internal.portable.PortableWriterExImpl;
+import org.apache.ignite.portable.PortableObject;
+
+/**
+ *
+ */
+public class PortablePlainPortableObject implements PortableLazyValue {
+    /** */
+    private final PortableObject portableObj;
+
+    /**
+     * @param portableObj Portable object.
+     */
+    public PortablePlainPortableObject(PortableObject portableObj) {
+        this.portableObj = portableObj;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object value() {
+        return portableObj;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
+        PortableObject val = portableObj;
+
+        if (val instanceof PortableObjectOffheapImpl)
+            val = ((PortableObjectOffheapImpl)val).heapCopy();
+
+        writer.doWritePortableObject((PortableObjectImpl)val);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableValueWithType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableValueWithType.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableValueWithType.java
new file mode 100644
index 0000000..2e031f0
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableValueWithType.java
@@ -0,0 +1,75 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+import org.apache.ignite.internal.portable.PortableWriterExImpl;
+import org.apache.ignite.internal.processors.cache.portable.CacheObjectPortableProcessorImpl;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ *
+ */
+class PortableValueWithType implements PortableLazyValue {
+    /** */
+    private byte type;
+
+    /** */
+    private Object val;
+
+    /**
+     * @param type Type
+     * @param val Value.
+     */
+    PortableValueWithType(byte type, Object val) {
+        this.type = type;
+        this.val = val;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
+        if (val instanceof PortableBuilderSerializationAware)
+            ((PortableBuilderSerializationAware)val).writeTo(writer, ctx);
+        else
+            ctx.writeValue(writer, val);
+    }
+
+    /** {@inheritDoc} */
+    public String typeName() {
+        return CacheObjectPortableProcessorImpl.fieldTypeName(type);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object value() {
+        if (val instanceof PortableLazyValue)
+            return ((PortableLazyValue)val).value();
+
+        return val;
+    }
+
+    /**
+     * @param val New value.
+     */
+    public void value(Object val) {
+        this.val = val;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(PortableValueWithType.class, this);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/package-info.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/package-info.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/package-info.java
new file mode 100644
index 0000000..e069f3e
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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 description. -->
+ * Contains classes specific to portable builder API.
+ */
+package org.apache.ignite.internal.portable.builder;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectPortableProcessorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectPortableProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectPortableProcessorImpl.java
index b33c643..1be5aea 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectPortableProcessorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectPortableProcessorImpl.java
@@ -45,13 +45,13 @@ import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.portable.GridPortableMarshaller;
-import org.apache.ignite.internal.portable.PortableBuilderImpl;
 import org.apache.ignite.internal.portable.PortableContext;
 import org.apache.ignite.internal.portable.PortableMetaDataHandler;
 import org.apache.ignite.internal.portable.PortableMetaDataImpl;
 import org.apache.ignite.internal.portable.PortableObjectImpl;
 import org.apache.ignite.internal.portable.PortableObjectOffheapImpl;
 import org.apache.ignite.internal.portable.PortableUtils;
+import org.apache.ignite.internal.portable.builder.PortableBuilderImpl;
 import org.apache.ignite.internal.portable.streams.PortableInputStream;
 import org.apache.ignite.internal.portable.streams.PortableOffheapInputStream;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/resources/META-INF/classnames.properties
----------------------------------------------------------------------
diff --git a/modules/core/src/main/resources/META-INF/classnames.properties b/modules/core/src/main/resources/META-INF/classnames.properties
index d80cc49..dd8c3f3 100644
--- a/modules/core/src/main/resources/META-INF/classnames.properties
+++ b/modules/core/src/main/resources/META-INF/classnames.properties
@@ -281,7 +281,7 @@ org.apache.ignite.internal.managers.loadbalancer.GridLoadBalancerManager$1
 org.apache.ignite.internal.processors.platform.PlatformAwareEventFilter
 org.apache.ignite.internal.portable.PortableClassDescriptor$Mode
 org.apache.ignite.internal.portable.PortableContext
-org.apache.ignite.internal.portable.PortableLazyMap$1$1$1
+org.apache.ignite.internal.portable.builder.PortableLazyMap$1$1$1
 org.apache.ignite.internal.portable.PortableMetaDataImpl
 org.apache.ignite.internal.portable.PortableObjectEx
 org.apache.ignite.internal.portable.PortableObjectImpl


[3/4] ignite git commit: ignite-1273: fixed cyclic references processing by PortableMarshaller and ability to modify array fields returned by PortableBuilder

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyMap.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyMap.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyMap.java
deleted file mode 100644
index eed8121..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyMap.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-import java.util.AbstractMap;
-import java.util.AbstractSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-import org.jetbrains.annotations.Nullable;
-
-/**
- *
- */
-class PortableLazyMap extends AbstractMap<Object, Object> implements PortableBuilderSerializationAware {
-    /** */
-    private final PortableBuilderReader reader;
-
-    /** */
-    private final int off;
-
-    /** */
-    private Map<Object, Object> delegate;
-
-    /**
-     * @param reader Reader.
-     * @param off Offset.
-     */
-    private PortableLazyMap(PortableBuilderReader reader, int off) {
-        this.reader = reader;
-        this.off = off;
-    }
-
-    /**
-     * @param reader Reader.
-     * @return PortableLazyMap.
-     */
-    @Nullable public static PortableLazyMap parseMap(PortableBuilderReader reader) {
-        int off = reader.position() - 1;
-
-        int size = reader.readInt();
-
-        reader.skip(1); // map type.
-
-        for (int i = 0; i < size; i++) {
-            reader.skipValue(); // skip key
-            reader.skipValue(); // skip value
-        }
-
-        return new PortableLazyMap(reader, off);
-    }
-
-    /**
-     *
-     */
-    private void ensureDelegateInit() {
-        if (delegate == null) {
-            int size = reader.readIntAbsolute(off + 1);
-
-            reader.position(off + 1/* flag */ + 4/* size */ + 1/* col type */);
-
-            delegate = new LinkedHashMap<>();
-
-            for (int i = 0; i < size; i++)
-                delegate.put(PortableUtils.unwrapLazy(reader.parseValue()), reader.parseValue());
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
-        if (delegate == null) {
-            int size = reader.readIntAbsolute(off + 1);
-
-            int hdrSize = 1 /* flag */ + 4 /* size */ + 1 /* col type */;
-            writer.write(reader.array(), off, hdrSize);
-
-            reader.position(off + hdrSize);
-
-            for (int i = 0; i < size; i++) {
-                ctx.writeValue(writer, reader.parseValue()); // key
-                ctx.writeValue(writer, reader.parseValue()); // value
-            }
-        }
-        else {
-            writer.writeByte(GridPortableMarshaller.MAP);
-            writer.writeInt(delegate.size());
-
-            byte colType = reader.array()[off + 1 /* flag */ + 4 /* size */];
-
-            writer.writeByte(colType);
-
-            for (Entry<Object, Object> entry : delegate.entrySet()) {
-                ctx.writeValue(writer, entry.getKey());
-                ctx.writeValue(writer, entry.getValue());
-            }
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override public int size() {
-        if (delegate == null)
-            return reader.readIntAbsolute(off + 1);
-
-        return delegate.size();
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean containsKey(Object key) {
-        ensureDelegateInit();
-
-        return delegate.containsKey(key);
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean containsValue(Object val) {
-        return values().contains(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public Set<Object> keySet() {
-        ensureDelegateInit();
-
-        return delegate.keySet();
-    }
-
-    /** {@inheritDoc} */
-    @Override public void clear() {
-        if (delegate == null)
-            delegate = new LinkedHashMap<>();
-        else
-            delegate.clear();
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object get(Object key) {
-        ensureDelegateInit();
-
-        return PortableUtils.unwrapLazy(delegate.get(key));
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object put(Object key, Object val) {
-        ensureDelegateInit();
-
-        return PortableUtils.unwrapLazy(delegate.put(key, val));
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object remove(Object key) {
-        ensureDelegateInit();
-
-        return PortableUtils.unwrapLazy(delegate.remove(key));
-    }
-
-    /** {@inheritDoc} */
-    @Override public Set<Entry<Object, Object>> entrySet() {
-        ensureDelegateInit();
-
-        return new AbstractSet<Entry<Object, Object>>() {
-            @Override public boolean contains(Object o) {
-                throw new UnsupportedOperationException();
-            }
-
-            @Override public Iterator<Entry<Object, Object>> iterator() {
-                return new Iterator<Entry<Object, Object>>() {
-                    /** */
-                    private final Iterator<Entry<Object, Object>> itr = delegate.entrySet().iterator();
-
-                    @Override public boolean hasNext() {
-                        return itr.hasNext();
-                    }
-
-                    @Override public Entry<Object, Object> next() {
-                        Entry<Object, Object> res = itr.next();
-
-                        final Object val = res.getValue();
-
-                        if (val instanceof PortableLazyValue) {
-                            return new SimpleEntry<Object, Object>(res.getKey(), val) {
-                                private static final long serialVersionUID = 0L;
-
-                                @Override public Object getValue() {
-                                    return ((PortableLazyValue)val).value();
-                                }
-                            };
-                        }
-
-                        return res;
-                    }
-
-                    @Override public void remove() {
-                        itr.remove();
-                    }
-                };
-            }
-
-            @Override public int size() {
-                return delegate.size();
-            }
-        };
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyMapEntry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyMapEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyMapEntry.java
deleted file mode 100644
index 1970d21..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyMapEntry.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-import java.util.Map;
-
-/**
- *
- */
-class PortableLazyMapEntry implements Map.Entry<Object, Object>, PortableBuilderSerializationAware {
-    /** */
-    private final Object key;
-
-    /** */
-    private Object val;
-
-    /**
-     * @param reader GridMutablePortableReader
-     */
-    PortableLazyMapEntry(PortableBuilderReader reader) {
-        key = reader.parseValue();
-        val = reader.parseValue();
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object getKey() {
-        return PortableUtils.unwrapLazy(key);
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object getValue() {
-        return PortableUtils.unwrapLazy(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object setValue(Object val) {
-        Object res = getValue();
-
-        this.val = val;
-
-        return res;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
-        writer.writeByte(GridPortableMarshaller.MAP_ENTRY);
-
-        ctx.writeValue(writer, key);
-        ctx.writeValue(writer, val);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazySet.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazySet.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazySet.java
deleted file mode 100644
index 3e1dc92..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazySet.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-import java.util.Collection;
-import java.util.Set;
-import org.apache.ignite.internal.util.typedef.internal.U;
-
-/**
- *
- */
-class PortableLazySet extends PortableAbstractLazyValue {
-    /** */
-    private final int off;
-
-    /**
-     * @param reader Reader.
-     * @param size Size.
-     */
-    PortableLazySet(PortableBuilderReader reader, int size) {
-        super(reader, reader.position() - 1);
-
-        off = reader.position() - 1/* flag */ - 4/* size */ - 1/* col type */;
-
-        assert size >= 0;
-
-        for (int i = 0; i < size; i++)
-            reader.skipValue();
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
-        if (val == null) {
-            int size = reader.readIntAbsolute(off + 1);
-
-            int hdrSize = 1 /* flag */ + 4 /* size */ + 1 /* col type */;
-            writer.write(reader.array(), off, hdrSize);
-
-            reader.position(off + hdrSize);
-
-            for (int i = 0; i < size; i++) {
-                Object o = reader.parseValue();
-
-                ctx.writeValue(writer, o);
-            }
-        }
-        else {
-            Collection<Object> c = (Collection<Object>)val;
-
-            writer.writeByte(GridPortableMarshaller.COL);
-            writer.writeInt(c.size());
-
-            byte colType = reader.array()[off + 1 /* flag */ + 4 /* size */];
-            writer.writeByte(colType);
-
-            for (Object o : c)
-                ctx.writeValue(writer, o);
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override protected Object init() {
-        int size = reader.readIntAbsolute(off + 1);
-
-        reader.position(off + 1/* flag */ + 4/* size */ + 1/* col type */);
-
-        Set<Object> res = U.newLinkedHashSet(size);
-
-        for (int i = 0; i < size; i++)
-            res.add(PortableUtils.unwrapLazy(reader.parseValue()));
-
-        return res;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyValue.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyValue.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyValue.java
deleted file mode 100644
index 43728b7..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyValue.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-/**
- *
- */
-interface PortableLazyValue extends PortableBuilderSerializationAware {
-    /**
-     * @return Value.
-     */
-    public Object value();
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectArrayLazyValue.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectArrayLazyValue.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectArrayLazyValue.java
deleted file mode 100644
index 897e8e8..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectArrayLazyValue.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.portable.PortableInvalidClassException;
-
-/**
- *
- */
-class PortableObjectArrayLazyValue extends PortableAbstractLazyValue {
-    /** */
-    private Object[] lazyValsArr;
-
-    /** */
-    private int compTypeId;
-
-    /** */
-    private String clsName;
-
-    /**
-     * @param reader Reader.
-     */
-    protected PortableObjectArrayLazyValue(PortableBuilderReader reader) {
-        super(reader, reader.position() - 1);
-
-        int typeId = reader.readInt();
-
-        if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) {
-            clsName = reader.readString();
-
-            Class cls;
-
-            try {
-                // TODO: IGNITE-1272 - Is class loader needed here?
-                cls = U.forName(reader.readString(), null);
-            }
-            catch (ClassNotFoundException e) {
-                throw new PortableInvalidClassException("Failed to load the class: " + clsName, e);
-            }
-
-            compTypeId = reader.portableContext().descriptorForClass(cls).typeId();
-        }
-        else {
-            compTypeId = typeId;
-            clsName = null;
-        }
-
-        int size = reader.readInt();
-
-        lazyValsArr = new Object[size];
-
-        for (int i = 0; i < size; i++)
-            lazyValsArr[i] = reader.parseValue();
-    }
-
-    /** {@inheritDoc} */
-    @Override protected Object init() {
-        for (int i = 0; i < lazyValsArr.length; i++) {
-            if (lazyValsArr[i] instanceof PortableLazyValue)
-                lazyValsArr[i] = ((PortableLazyValue)lazyValsArr[i]).value();
-        }
-
-        return lazyValsArr;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
-        if (clsName == null)
-            ctx.writeArray(writer, GridPortableMarshaller.OBJ_ARR, lazyValsArr, compTypeId);
-        else
-            ctx.writeArray(writer, GridPortableMarshaller.OBJ_ARR, lazyValsArr, clsName);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortablePlainLazyValue.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortablePlainLazyValue.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortablePlainLazyValue.java
deleted file mode 100644
index d08d09b..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortablePlainLazyValue.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-/**
- *
- */
-class PortablePlainLazyValue extends PortableAbstractLazyValue {
-    /** */
-    protected final int len;
-
-    /**
-     * @param reader Reader
-     * @param valOff Offset
-     * @param len Length.
-     */
-    protected PortablePlainLazyValue(PortableBuilderReader reader, int valOff, int len) {
-        super(reader, valOff);
-
-        this.len = len;
-    }
-
-    /** {@inheritDoc} */
-    @Override protected Object init() {
-        return reader.reader().unmarshal(valOff);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
-        writer.write(reader.array(), valOff, len);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortablePlainPortableObject.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortablePlainPortableObject.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortablePlainPortableObject.java
deleted file mode 100644
index cfaa04f..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortablePlainPortableObject.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-import org.apache.ignite.portable.PortableObject;
-
-/**
- *
- */
-public class PortablePlainPortableObject implements PortableLazyValue {
-    /** */
-    private final PortableObject portableObj;
-
-    /**
-     * @param portableObj Portable object.
-     */
-    public PortablePlainPortableObject(PortableObject portableObj) {
-        this.portableObj = portableObj;
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object value() {
-        return portableObj;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
-        PortableObject val = portableObj;
-
-        if (val instanceof PortableObjectOffheapImpl)
-            val = ((PortableObjectOffheapImpl)val).heapCopy();
-
-        writer.doWritePortableObject((PortableObjectImpl)val);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableReaderExImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableReaderExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableReaderExImpl.java
index f702e06..83ccb65 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableReaderExImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableReaderExImpl.java
@@ -156,7 +156,7 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
      * @param start Start.
      * @param ldr Class loader.
      */
-    PortableReaderExImpl(PortableContext ctx, byte[] arr, int start, ClassLoader ldr) {
+    public PortableReaderExImpl(PortableContext ctx, byte[] arr, int start, ClassLoader ldr) {
         this(ctx, new PortableHeapInputStream(arr), start, ldr, new PortableReaderContext());
     }
 
@@ -256,7 +256,7 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
      * @return Unmarshalled value.
      * @throws PortableException In case of error.
      */
-    Object unmarshal(int offset) throws PortableException {
+    public Object unmarshal(int offset) throws PortableException {
         off = offset;
 
         return off >= 0 ? unmarshal(false) : null;
@@ -586,6 +586,9 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             if (flag == NULL)
                 return null;
 
+            if (flag == HANDLE)
+                return readHandleField();
+
             if (flag != BYTE_ARR)
                 throw new PortableException("Invalid flag value: " + flag);
 
@@ -609,6 +612,9 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             if (flag == NULL)
                 return null;
 
+            if (flag == HANDLE)
+                return readHandleField();
+
             if (flag != SHORT_ARR)
                 throw new PortableException("Invalid flag value: " + flag);
 
@@ -632,6 +638,9 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             if (flag == NULL)
                 return null;
 
+            if (flag == HANDLE)
+                return readHandleField();
+
             if (flag != INT_ARR)
                 throw new PortableException("Invalid flag value: " + flag);
 
@@ -655,6 +664,9 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             if (flag == NULL)
                 return null;
 
+            if (flag == HANDLE)
+                return readHandleField();
+
             if (flag != LONG_ARR)
                 throw new PortableException("Invalid flag value: " + flag);
 
@@ -678,6 +690,9 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             if (flag == NULL)
                 return null;
 
+            if (flag == HANDLE)
+                return readHandleField();
+
             if (flag != FLOAT_ARR)
                 throw new PortableException("Invalid flag value: " + flag);
 
@@ -701,6 +716,9 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             if (flag == NULL)
                 return null;
 
+            if (flag == HANDLE)
+                return readHandleField();
+
             if (flag != DOUBLE_ARR)
                 throw new PortableException("Invalid flag value: " + flag);
 
@@ -724,6 +742,9 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             if (flag == NULL)
                 return null;
 
+            if (flag == HANDLE)
+                return readHandleField();
+
             if (flag != CHAR_ARR)
                 throw new PortableException("Invalid flag value: " + flag);
 
@@ -747,6 +768,9 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             if (flag == NULL)
                 return null;
 
+            if (flag == HANDLE)
+                return readHandleField();
+
             if (flag != BOOLEAN_ARR)
                 throw new PortableException("Invalid flag value: " + flag);
 
@@ -770,6 +794,9 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             if (flag == NULL)
                 return null;
 
+            if (flag == HANDLE)
+                return readHandleField();
+
             if (flag != DECIMAL_ARR)
                 throw new PortableException("Invalid flag value: " + flag);
 
@@ -793,6 +820,9 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             if (flag == NULL)
                 return null;
 
+            if (flag == HANDLE)
+                return readHandleField();
+
             if (flag != STRING_ARR)
                 throw new PortableException("Invalid flag value: " + flag);
 
@@ -816,6 +846,9 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             if (flag == NULL)
                 return null;
 
+            if (flag == HANDLE)
+                return readHandleField();
+
             if (flag != UUID_ARR)
                 throw new PortableException("Invalid flag value: " + flag);
 
@@ -839,6 +872,9 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             if (flag == NULL)
                 return null;
 
+            if (flag == HANDLE)
+                return readHandleField();
+
             if (flag != DATE_ARR)
                 throw new PortableException("Invalid flag value: " + flag);
 
@@ -862,6 +898,9 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             if (flag == NULL)
                 return null;
 
+            if (flag == HANDLE)
+                return readHandleField();
+
             if (flag != OBJ_ARR)
                 throw new PortableException("Invalid flag value: " + flag);
 
@@ -887,6 +926,9 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             if (flag == NULL)
                 return null;
 
+            if (flag == HANDLE)
+                return readHandleField();
+
             if (flag != COL)
                 throw new PortableException("Invalid flag value: " + flag);
 
@@ -912,6 +954,9 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             if (flag == NULL)
                 return null;
 
+            if (flag == HANDLE)
+                return readHandleField();
+
             if (flag != MAP)
                 throw new PortableException("Invalid flag value: " + flag);
 
@@ -935,10 +980,13 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             if (flag == NULL)
                 return null;
 
+            if (flag == HANDLE)
+                return readHandleField();
+
             if (flag != MAP_ENTRY)
                 throw new PortableException("Invalid flag value: " + flag);
 
-            return new GridMapEntry<>(doReadObject(false), doReadObject(false));
+            return doReadMapEntry(false, true);
         }
         else
             return null;
@@ -1059,6 +1107,33 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
         rCtx.setObjectHandler(start, obj);
     }
 
+    /**
+     * @param obj Object.
+     * @param pos Position.
+     */
+    void setHandler(Object obj, int pos) {
+        rCtx.setObjectHandler(pos, obj);
+    }
+
+    /**
+     * Recreating field value from a handle.
+     *
+     * @param <T> Field type.
+     * @return Field.
+     */
+    private <T> T readHandleField() {
+        int handle = (off - 1) - doReadInt(false);
+
+        Object obj = rCtx.getObjectByHandle(handle);
+
+        if (obj == null) {
+            off = handle;
+
+            obj = doReadObject(false);
+        }
+
+        return (T)obj;
+    }
     /** {@inheritDoc} */
     @Override public byte readByte(String fieldName) throws PortableException {
         Byte val = readByte(fieldId(fieldName));
@@ -1676,7 +1751,7 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
                 else
                     po = in.offheapPointer() > 0
                         ? new PortableObjectOffheapImpl(ctx, in.offheapPointer(), start,
-                                                            in.remaining() + in.position())
+                        in.remaining() + in.position())
                         : new PortableObjectImpl(ctx, in.array(), start);
 
                 rCtx.setPortableHandler(start, po);
@@ -1805,7 +1880,6 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
 
                 return obj;
 
-
             default:
                 throw new PortableException("Invalid flag value: " + flag);
         }
@@ -2306,12 +2380,16 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
      * @return Value.
      */
     private byte[] doReadByteArray(boolean raw) {
+        int hPos = (raw ? rawOff : off) - 1;
+
         int len = doReadInt(raw);
 
         in.position(raw ? rawOff : off);
 
         byte[] arr = in.readByteArray(len);
 
+        setHandler(arr, hPos);
+
         if (raw)
             rawOff += len;
         else
@@ -2325,12 +2403,16 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
      * @return Value.
      */
     private short[] doReadShortArray(boolean raw) {
+        int hPos = (raw ? rawOff : off) - 1;
+
         int len = doReadInt(raw);
 
         in.position(raw ? rawOff : off);
 
         short[] arr = in.readShortArray(len);
 
+        setHandler(arr, hPos);
+
         int bytes = len << 1;
 
         if (raw)
@@ -2346,12 +2428,16 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
      * @return Value.
      */
     private int[] doReadIntArray(boolean raw) {
+        int hPos = (raw ? rawOff : off) - 1;
+
         int len = doReadInt(raw);
 
         in.position(raw ? rawOff : off);
 
         int[] arr = in.readIntArray(len);
 
+        setHandler(arr, hPos);
+
         int bytes = len << 2;
 
         if (raw)
@@ -2367,12 +2453,16 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
      * @return Value.
      */
     private long[] doReadLongArray(boolean raw) {
+        int hPos = (raw ? rawOff : off) - 1;
+
         int len = doReadInt(raw);
 
         in.position(raw ? rawOff : off);
 
         long[] arr = in.readLongArray(len);
 
+        setHandler(arr, hPos);
+
         int bytes = len << 3;
 
         if (raw)
@@ -2388,12 +2478,16 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
      * @return Value.
      */
     private float[] doReadFloatArray(boolean raw) {
+        int hPos = (raw ? rawOff : off) - 1;
+
         int len = doReadInt(raw);
 
         in.position(raw ? rawOff : off);
 
         float[] arr = in.readFloatArray(len);
 
+        setHandler(arr, hPos);
+
         int bytes = len << 2;
 
         if (raw)
@@ -2409,12 +2503,16 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
      * @return Value.
      */
     private double[] doReadDoubleArray(boolean raw) {
+        int hPos = (raw ? rawOff : off) - 1;
+
         int len = doReadInt(raw);
 
         in.position(raw ? rawOff : off);
 
         double[] arr = in.readDoubleArray(len);
 
+        setHandler(arr, hPos);
+
         int bytes = len << 3;
 
         if (raw)
@@ -2430,12 +2528,16 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
      * @return Value.
      */
     private char[] doReadCharArray(boolean raw) {
+        int hPos = (raw ? rawOff : off) - 1;
+
         int len = doReadInt(raw);
 
         in.position(raw ? rawOff : off);
 
         char[] arr = in.readCharArray(len);
 
+        setHandler(arr, hPos);
+
         int bytes = len << 1;
 
         if (raw)
@@ -2451,12 +2553,16 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
      * @return Value.
      */
     private boolean[] doReadBooleanArray(boolean raw) {
+        int hPos = (raw ? rawOff : off) - 1;
+
         int len = doReadInt(raw);
 
         in.position(raw ? rawOff : off);
 
         boolean[] arr = in.readBooleanArray(len);
 
+        setHandler(arr, hPos);
+
         if (raw)
             rawOff += len;
         else
@@ -2471,10 +2577,14 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
      * @throws PortableException In case of error.
      */
     private BigDecimal[] doReadDecimalArray(boolean raw) throws PortableException {
+        int hPos = (raw ? rawOff : off) - 1;
+
         int len = doReadInt(raw);
 
         BigDecimal[] arr = new BigDecimal[len];
 
+        setHandler(arr, hPos);
+
         for (int i = 0; i < len; i++) {
             byte flag = doReadByte(raw);
 
@@ -2497,10 +2607,14 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
      * @throws PortableException In case of error.
      */
     private String[] doReadStringArray(boolean raw) throws PortableException {
+        int hPos = (raw ? rawOff : off) - 1;
+
         int len = doReadInt(raw);
 
         String[] arr = new String[len];
 
+        setHandler(arr, hPos);
+
         for (int i = 0; i < len; i++) {
             byte flag = doReadByte(raw);
 
@@ -2523,10 +2637,14 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
      * @throws PortableException In case of error.
      */
     private UUID[] doReadUuidArray(boolean raw) throws PortableException {
+        int hPos = (raw ? rawOff : off) - 1;
+
         int len = doReadInt(raw);
 
         UUID[] arr = new UUID[len];
 
+        setHandler(arr, hPos);
+
         for (int i = 0; i < len; i++) {
             byte flag = doReadByte(raw);
 
@@ -2549,10 +2667,14 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
      * @throws PortableException In case of error.
      */
     private Date[] doReadDateArray(boolean raw) throws PortableException {
+        int hPos = (raw ? rawOff : off) - 1;
+
         int len = doReadInt(raw);
 
         Date[] arr = new Date[len];
 
+        setHandler(arr, hPos);
+
         for (int i = 0; i < len; i++) {
             byte flag = doReadByte(raw);
 
@@ -2576,12 +2698,16 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
      * @throws PortableException In case of error.
      */
     private Object[] doReadObjectArray(boolean raw, boolean deep) throws PortableException {
+        int hPos = (raw ? rawOff : off) - 1;
+
         Class compType = doReadClass(raw);
 
         int len = doReadInt(raw);
 
         Object[] arr = deep ? (Object[])Array.newInstance(compType, len) : new Object[len];
 
+        setHandler(arr, hPos);
+
         for (int i = 0; i < len; i++)
             arr[i] = deep ? doReadObject(raw) : unmarshal(raw);
 
@@ -2598,6 +2724,8 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
     @SuppressWarnings("unchecked")
     private Collection<?> doReadCollection(boolean raw, boolean deep, @Nullable Class<? extends Collection> cls)
         throws PortableException {
+        int hPos = (raw ? rawOff : off) - 1;
+
         int size = doReadInt(raw);
 
         assert size >= 0;
@@ -2667,6 +2795,8 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             }
         }
 
+        setHandler(col, hPos);
+
         for (int i = 0; i < size; i++)
             col.add(deep ? doReadObject(raw) : unmarshal(raw));
 
@@ -2683,6 +2813,8 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
     @SuppressWarnings("unchecked")
     private Map<?, ?> doReadMap(boolean raw, boolean deep, @Nullable Class<? extends Map> cls)
         throws PortableException {
+        int hPos = (raw ? rawOff : off) - 1;
+
         int size = doReadInt(raw);
 
         assert size >= 0;
@@ -2742,6 +2874,8 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
             }
         }
 
+        setHandler(map, hPos);
+
         for (int i = 0; i < size; i++)
             map.put(deep ? doReadObject(raw) : unmarshal(raw), deep ? doReadObject(raw) : unmarshal(raw));
 
@@ -2755,10 +2889,16 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
      * @throws PortableException In case of error.
      */
     private Map.Entry<?, ?> doReadMapEntry(boolean raw, boolean deep) throws PortableException {
+        int hPos = (raw ? rawOff : off) - 1;
+
         Object val1 = deep ? doReadObject(raw) : unmarshal(raw);
         Object val2 = deep ? doReadObject(raw) : unmarshal(raw);
 
-        return new GridMapEntry<>(val1, val2);
+        GridMapEntry entry = new GridMapEntry<>(val1, val2);
+
+        setHandler(entry, hPos);
+
+        return entry;
     }
 
     /**
@@ -3017,4 +3157,4 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx
     @Override public void close() throws IOException {
         // No-op.
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java
index ce77783..7259cc9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java
@@ -33,6 +33,7 @@ import java.util.TreeSet;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentSkipListSet;
+import org.apache.ignite.internal.portable.builder.PortableLazyValue;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.portable.PortableObject;
 import org.jetbrains.annotations.Nullable;
@@ -359,6 +360,16 @@ public class PortableUtils {
     }
 
     /**
+     * Checks whether an array type values can or can not contain references to other object.
+     *
+     * @param type Array type.
+     * @return {@code true} if content of serialized array value cannot contain references to other object.
+     */
+    public static boolean isPlainArrayType(int type) {
+        return type >= BYTE_ARR && type <= DATE_ARR;
+    }
+
+    /**
      * @param cls Class.
      * @return Portable field type.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableValueWithType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableValueWithType.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableValueWithType.java
deleted file mode 100644
index ebc68c1..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableValueWithType.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-import org.apache.ignite.internal.processors.cache.portable.CacheObjectPortableProcessorImpl;
-import org.apache.ignite.internal.util.typedef.internal.S;
-
-/**
- *
- */
-class PortableValueWithType implements PortableLazyValue {
-    /** */
-    private byte type;
-
-    /** */
-    private Object val;
-
-    /**
-     * @param type Type
-     * @param val Value.
-     */
-    PortableValueWithType(byte type, Object val) {
-        this.type = type;
-        this.val = val;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
-        if (val instanceof PortableBuilderSerializationAware)
-            ((PortableBuilderSerializationAware)val).writeTo(writer, ctx);
-        else
-            ctx.writeValue(writer, val);
-    }
-
-    /** {@inheritDoc} */
-    public String typeName() {
-        return CacheObjectPortableProcessorImpl.fieldTypeName(type);
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object value() {
-        if (val instanceof PortableLazyValue)
-            return ((PortableLazyValue)val).value();
-
-        return val;
-    }
-
-    /**
-     * @param val New value.
-     */
-    public void value(Object val) {
-        this.val = val;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(PortableValueWithType.class, this);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableWriterExImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableWriterExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableWriterExImpl.java
index 6bcce2b..364d5f8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableWriterExImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableWriterExImpl.java
@@ -156,7 +156,7 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
      * @param off Start offset.
      * @param typeId Type ID.
      */
-    PortableWriterExImpl(PortableContext ctx, int off, int typeId, boolean metaEnabled) {
+    public PortableWriterExImpl(PortableContext ctx, int off, int typeId, boolean metaEnabled) {
         this(ctx, off);
 
         this.typeId = typeId;
@@ -320,14 +320,14 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
     /**
      * @return Array.
      */
-    byte[] array() {
+    public byte[] array() {
         return wCtx.out.arrayCopy();
     }
 
     /**
      * @return Output stream.
      */
-    PortableOutputStream outputStream() {
+    public PortableOutputStream outputStream() {
         return wCtx.out;
     }
 
@@ -351,7 +351,7 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
      * @param bytes Number of bytes to reserve.
      * @return Offset.
      */
-    int reserve(int bytes) {
+    public int reserve(int bytes) {
         int pos = wCtx.out.position();
 
         wCtx.out.position(pos + bytes);
@@ -363,7 +363,7 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
      * @param bytes Number of bytes to reserve.
      * @return Offset.
      */
-    int reserveAndMark(int bytes) {
+    public int reserveAndMark(int bytes) {
         int off0 = reserve(bytes);
 
         mark = wCtx.out.position();
@@ -374,21 +374,21 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
     /**
      * @param off Offset.
      */
-    void writeDelta(int off) {
+    public void writeDelta(int off) {
         wCtx.out.writeInt(off, wCtx.out.position() - mark);
     }
 
     /**
      *
      */
-    void writeLength() {
+    public void writeLength() {
         wCtx.out.writeInt(start + TOTAL_LEN_POS, wCtx.out.position() - start);
     }
 
     /**
      *
      */
-    void writeRawOffsetIfNeeded() {
+    public void writeRawOffsetIfNeeded() {
         if (allowFields)
             wCtx.out.writeInt(start + RAW_DATA_OFF_POS, wCtx.out.position() - start);
     }
@@ -416,63 +416,63 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
     /**
      * @param val Value.
      */
-    void doWriteByte(byte val) {
+    public void doWriteByte(byte val) {
         wCtx.out.writeByte(val);
     }
 
     /**
      * @param val Value.
      */
-    void doWriteShort(short val) {
+    public void doWriteShort(short val) {
         wCtx.out.writeShort(val);
     }
 
     /**
      * @param val Value.
      */
-    void doWriteInt(int val) {
+    public void doWriteInt(int val) {
         wCtx.out.writeInt(val);
     }
 
     /**
      * @param val Value.
      */
-    void doWriteLong(long val) {
+    public void doWriteLong(long val) {
         wCtx.out.writeLong(val);
     }
 
     /**
      * @param val Value.
      */
-    void doWriteFloat(float val) {
+    public void doWriteFloat(float val) {
         wCtx.out.writeFloat(val);
     }
 
     /**
      * @param val Value.
      */
-    void doWriteDouble(double val) {
+    public void doWriteDouble(double val) {
         wCtx.out.writeDouble(val);
     }
 
     /**
      * @param val Value.
      */
-    void doWriteChar(char val) {
+    public void doWriteChar(char val) {
         wCtx.out.writeChar(val);
     }
 
     /**
      * @param val Value.
      */
-    void doWriteBoolean(boolean val) {
+    public void doWriteBoolean(boolean val) {
         wCtx.out.writeBoolean(val);
     }
 
     /**
      * @param val String value.
      */
-    void doWriteDecimal(@Nullable BigDecimal val) {
+    public void doWriteDecimal(@Nullable BigDecimal val) {
         if (val == null)
             doWriteByte(NULL);
         else {
@@ -498,7 +498,7 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
     /**
      * @param val String value.
      */
-    void doWriteString(@Nullable String val) {
+    public void doWriteString(@Nullable String val) {
         if (val == null)
             doWriteByte(NULL);
         else {
@@ -528,7 +528,7 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
     /**
      * @param uuid UUID.
      */
-    void doWriteUuid(@Nullable UUID uuid) {
+    public void doWriteUuid(@Nullable UUID uuid) {
         if (uuid == null)
             doWriteByte(NULL);
         else {
@@ -541,7 +541,7 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
     /**
      * @param date Date.
      */
-    void doWriteDate(@Nullable Date date) {
+    public void doWriteDate(@Nullable Date date) {
         if (date == null)
             doWriteByte(NULL);
         else {
@@ -554,7 +554,7 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
     /**
      * @param ts Timestamp.
      */
-    void doWriteTimestamp(@Nullable Timestamp ts) {
+    public void doWriteTimestamp(@Nullable Timestamp ts) {
         if (ts == null)
             doWriteByte(NULL);
         else {
@@ -569,7 +569,7 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
      * @param detached Detached or not.
      * @throws PortableException In case of error.
      */
-    void doWriteObject(@Nullable Object obj, boolean detached) throws PortableException {
+    public void doWriteObject(@Nullable Object obj, boolean detached) throws PortableException {
         if (obj == null)
             doWriteByte(NULL);
         else {
@@ -591,6 +591,9 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         if (val == null)
             doWriteByte(NULL);
         else {
+            if (tryWriteAsHandle(val))
+                return;
+
             doWriteByte(BYTE_ARR);
             doWriteInt(val.length);
 
@@ -605,6 +608,9 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         if (val == null)
             doWriteByte(NULL);
         else {
+            if (tryWriteAsHandle(val))
+                return;
+
             doWriteByte(SHORT_ARR);
             doWriteInt(val.length);
 
@@ -619,6 +625,9 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         if (val == null)
             doWriteByte(NULL);
         else {
+            if (tryWriteAsHandle(val))
+                return;
+
             doWriteByte(INT_ARR);
             doWriteInt(val.length);
 
@@ -633,6 +642,9 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         if (val == null)
             doWriteByte(NULL);
         else {
+            if (tryWriteAsHandle(val))
+                return;
+
             doWriteByte(LONG_ARR);
             doWriteInt(val.length);
 
@@ -647,6 +659,9 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         if (val == null)
             doWriteByte(NULL);
         else {
+            if (tryWriteAsHandle(val))
+                return;
+
             doWriteByte(FLOAT_ARR);
             doWriteInt(val.length);
 
@@ -661,6 +676,9 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         if (val == null)
             doWriteByte(NULL);
         else {
+            if (tryWriteAsHandle(val))
+                return;
+
             doWriteByte(DOUBLE_ARR);
             doWriteInt(val.length);
 
@@ -675,6 +693,9 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         if (val == null)
             doWriteByte(NULL);
         else {
+            if (tryWriteAsHandle(val))
+                return;
+
             doWriteByte(CHAR_ARR);
             doWriteInt(val.length);
 
@@ -689,6 +710,9 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         if (val == null)
             doWriteByte(NULL);
         else {
+            if (tryWriteAsHandle(val))
+                return;
+
             doWriteByte(BOOLEAN_ARR);
             doWriteInt(val.length);
 
@@ -703,6 +727,9 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         if (val == null)
             doWriteByte(NULL);
         else {
+            if (tryWriteAsHandle(val))
+                return;
+
             doWriteByte(DECIMAL_ARR);
             doWriteInt(val.length);
 
@@ -718,6 +745,9 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         if (val == null)
             doWriteByte(NULL);
         else {
+            if (tryWriteAsHandle(val))
+                return;
+
             doWriteByte(STRING_ARR);
             doWriteInt(val.length);
 
@@ -733,6 +763,9 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         if (val == null)
             doWriteByte(NULL);
         else {
+            if (tryWriteAsHandle(val))
+                return;
+
             doWriteByte(UUID_ARR);
             doWriteInt(val.length);
 
@@ -748,6 +781,9 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         if (val == null)
             doWriteByte(NULL);
         else {
+            if (tryWriteAsHandle(val))
+                return;
+
             doWriteByte(DATE_ARR);
             doWriteInt(val.length);
 
@@ -764,6 +800,9 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         if (val == null)
             doWriteByte(NULL);
         else {
+            if (tryWriteAsHandle(val))
+                return;
+
             PortableContext.Type type = ctx.typeId(val.getClass().getComponentType());
 
             doWriteByte(OBJ_ARR);
@@ -790,6 +829,9 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         if (col == null)
             doWriteByte(NULL);
         else {
+            if (tryWriteAsHandle(col))
+                return;
+
             doWriteByte(COL);
             doWriteInt(col.size());
             doWriteByte(ctx.collectionType(col.getClass()));
@@ -807,6 +849,9 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         if (map == null)
             doWriteByte(NULL);
         else {
+            if (tryWriteAsHandle(map))
+                return;
+
             doWriteByte(MAP);
             doWriteInt(map.size());
             doWriteByte(ctx.mapType(map.getClass()));
@@ -826,6 +871,9 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         if (e == null)
             doWriteByte(NULL);
         else {
+            if (tryWriteAsHandle(e))
+                return;
+
             doWriteByte(MAP_ENTRY);
             doWriteObject(e.getKey(), false);
             doWriteObject(e.getValue(), false);
@@ -905,7 +953,7 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
     /**
      * @param po Portable object.
      */
-    void doWritePortableObject(@Nullable PortableObjectImpl po) {
+    public void doWritePortableObject(@Nullable PortableObjectImpl po) {
         if (po == null)
             doWriteByte(NULL);
         else {
@@ -1106,64 +1154,88 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
      * @param val Value.
      */
     void writeByteArrayField(@Nullable byte[] val) {
-        doWriteInt(val != null ? 5 + val.length : 1);
+        int lenPos = reserveAndMark(4);
+
         doWriteByteArray(val);
+
+        writeDelta(lenPos);
     }
 
     /**
      * @param val Value.
      */
     void writeShortArrayField(@Nullable short[] val) {
-        doWriteInt(val != null ? 5 + (val.length << 1) : 1);
+        int lenPos = reserveAndMark(4);
+
         doWriteShortArray(val);
+
+        writeDelta(lenPos);
     }
 
     /**
      * @param val Value.
      */
     void writeIntArrayField(@Nullable int[] val) {
-        doWriteInt(val != null ? 5 + (val.length << 2) : 1);
+        int lenPos = reserveAndMark(4);
+
         doWriteIntArray(val);
+
+        writeDelta(lenPos);
     }
 
     /**
      * @param val Value.
      */
     void writeLongArrayField(@Nullable long[] val) {
-        doWriteInt(val != null ? 5 + (val.length << 3) : 1);
+        int lenPos = reserveAndMark(4);
+
         doWriteLongArray(val);
+
+        writeDelta(lenPos);
     }
 
     /**
      * @param val Value.
      */
     void writeFloatArrayField(@Nullable float[] val) {
-        doWriteInt(val != null ? 5 + (val.length << 2) : 1);
+        int lenPos = reserveAndMark(4);
+
         doWriteFloatArray(val);
+
+        writeDelta(lenPos);
     }
 
     /**
      * @param val Value.
      */
     void writeDoubleArrayField(@Nullable double[] val) {
-        doWriteInt(val != null ? 5 + (val.length << 3) : 1);
+        int lenPos = reserveAndMark(4);
+
         doWriteDoubleArray(val);
+
+        writeDelta(lenPos);
     }
 
     /**
      * @param val Value.
      */
     void writeCharArrayField(@Nullable char[] val) {
-        doWriteInt(val != null ? 5 + (val.length << 1) : 1);
+        int lenPos = reserveAndMark(4);
+
         doWriteCharArray(val);
+
+        writeDelta(lenPos);
     }
 
     /**
      * @param val Value.
      */
     void writeBooleanArrayField(@Nullable boolean[] val) {
-        doWriteInt(val != null ? 5 + val.length : 1);
+        int lenPos = reserveAndMark(4);
+
         doWriteBooleanArray(val);
+
+        writeDelta(lenPos);
     }
 
     /**
@@ -1739,12 +1811,31 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
         doWriteInt(id);
     }
 
+     /**
+      * Attempts to write the object as a handle.
+      *
+      * @param obj Object to write.
+      * @return {@code true} if the object has been written as a handle.
+      */
+     boolean tryWriteAsHandle(Object obj) {
+         int handle = handle(obj);
+
+         if (handle >= 0) {
+             doWriteByte(GridPortableMarshaller.HANDLE);
+             doWriteInt(handle);
+
+             return true;
+         }
+
+         return false;
+     }
+
     /**
      * Create new writer with same context.
      * @param typeId type
      * @return New writer.
      */
-    PortableWriterExImpl newWriter(int typeId) {
+    public PortableWriterExImpl newWriter(int typeId) {
         PortableWriterExImpl res = new PortableWriterExImpl(ctx, wCtx);
 
         res.typeId = typeId;
@@ -1755,7 +1846,7 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
     /**
      * @return Portable context.
      */
-    PortableContext context() {
+    public PortableContext context() {
         return ctx;
     }
 
@@ -1803,4 +1894,4 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx
             handles = new IdentityHashMap<>();
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableAbstractLazyValue.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableAbstractLazyValue.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableAbstractLazyValue.java
new file mode 100644
index 0000000..1f521ac
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableAbstractLazyValue.java
@@ -0,0 +1,57 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+/**
+ *
+ */
+abstract class PortableAbstractLazyValue implements PortableLazyValue {
+    /** */
+    protected Object val;
+
+    /** */
+    protected final PortableBuilderReader reader;
+
+    /** */
+    protected final int valOff;
+
+    /**
+     * @param reader Reader.
+     * @param valOff Value.
+     */
+    protected PortableAbstractLazyValue(PortableBuilderReader reader, int valOff) {
+        this.reader = reader;
+        this.valOff = valOff;
+    }
+
+    /**
+     * @return Value.
+     */
+    protected abstract Object init();
+
+    /** {@inheritDoc} */
+    @Override public Object value() {
+        if (val == null) {
+            val = init();
+
+            assert val != null;
+        }
+
+        return val;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderEnum.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderEnum.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderEnum.java
new file mode 100644
index 0000000..1472d56
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderEnum.java
@@ -0,0 +1,116 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+import org.apache.ignite.internal.portable.GridPortableMarshaller;
+import org.apache.ignite.internal.portable.PortableWriterExImpl;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.portable.PortableInvalidClassException;
+
+/**
+ *
+ */
+public class PortableBuilderEnum implements PortableBuilderSerializationAware {
+    /** */
+    private final int ordinal;
+
+    /** */
+    private final int typeId;
+
+    /** */
+    private final String clsName;
+
+    /**
+     * @param typeId Type ID.
+     * @param anEnum Enum instance.
+     */
+    public PortableBuilderEnum(int typeId, Enum anEnum) {
+        ordinal = anEnum.ordinal();
+        this.typeId = typeId;
+        clsName = null;
+    }
+
+    /**
+     * @param reader PortableBuilderReader.
+     */
+    public PortableBuilderEnum(PortableBuilderReader reader) {
+        int typeId = reader.readInt();
+
+        if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) {
+            clsName = reader.readString();
+
+            Class cls;
+
+            try {
+                // TODO: IGNITE-1272 - Is class loader needed here?
+                cls = U.forName(reader.readString(), null);
+            }
+            catch (ClassNotFoundException e) {
+                throw new PortableInvalidClassException("Failed to load the class: " + clsName, e);
+            }
+
+            this.typeId = reader.portableContext().descriptorForClass(cls).typeId();
+        }
+        else {
+            this.typeId = typeId;
+            this.clsName = null;
+        }
+
+        ordinal = reader.readInt();
+    }
+
+    /**
+     * @return Ordinal.
+     */
+    public int getOrdinal() {
+        return ordinal;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
+        writer.writeByte(GridPortableMarshaller.ENUM);
+
+        if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) {
+            writer.writeInt(GridPortableMarshaller.UNREGISTERED_TYPE_ID);
+            writer.writeString(clsName);
+        }
+        else
+            writer.writeInt(typeId);
+
+        writer.writeInt(ordinal);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        PortableBuilderEnum that = (PortableBuilderEnum)o;
+
+        return ordinal == that.ordinal && typeId == that.typeId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int result = ordinal;
+
+        result = 31 * result + typeId;
+
+        return result;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderImpl.java
new file mode 100644
index 0000000..b2e4c0d
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderImpl.java
@@ -0,0 +1,537 @@
+/*
+ * 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.ignite.internal.portable.builder;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import org.apache.ignite.internal.processors.cache.portable.CacheObjectPortableProcessorImpl;
+import org.apache.ignite.internal.util.GridArgumentCheck;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.portable.PortableBuilder;
+import org.apache.ignite.portable.PortableException;
+import org.apache.ignite.portable.PortableInvalidClassException;
+import org.apache.ignite.portable.PortableMetadata;
+import org.apache.ignite.portable.PortableObject;
+import org.jetbrains.annotations.Nullable;
+import org.apache.ignite.internal.portable.*;
+import org.apache.ignite.internal.processors.cache.portable.*;
+import org.apache.ignite.internal.util.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+import org.apache.ignite.portable.*;
+
+import static org.apache.ignite.internal.portable.GridPortableMarshaller.CLS_NAME_POS;
+import static org.apache.ignite.internal.portable.GridPortableMarshaller.DFLT_HDR_LEN;
+import static org.apache.ignite.internal.portable.GridPortableMarshaller.HASH_CODE_POS;
+import static org.apache.ignite.internal.portable.GridPortableMarshaller.RAW_DATA_OFF_POS;
+import static org.apache.ignite.internal.portable.GridPortableMarshaller.TOTAL_LEN_POS;
+import static org.apache.ignite.internal.portable.GridPortableMarshaller.TYPE_ID_POS;
+import static org.apache.ignite.internal.portable.GridPortableMarshaller.UNREGISTERED_TYPE_ID;
+
+/**
+ *
+ */
+public class PortableBuilderImpl implements PortableBuilder {
+    /** */
+    private static final Object REMOVED_FIELD_MARKER = new Object();
+
+    /** */
+    private final PortableContext ctx;
+
+    /** */
+    private final int typeId;
+
+    /** May be null. */
+    private String typeName;
+
+    /** May be null. */
+    private String clsNameToWrite;
+
+    /** */
+    private boolean registeredType = true;
+
+    /** */
+    private Map<String, Object> assignedVals;
+
+    /** */
+    private Map<Integer, Object> readCache;
+
+    /** Position of object in source array, or -1 if object is not created from PortableObject. */
+    private final int start;
+
+    /** Total header length */
+    private final int hdrLen;
+
+    /**
+     * Context of PortableObject reading process. Or {@code null} if object is not created from PortableObject.
+     */
+    private final PortableBuilderReader reader;
+
+    /** */
+    private int hashCode;
+
+    /**
+     * @param clsName Class name.
+     * @param ctx Portable context.
+     */
+    public PortableBuilderImpl(PortableContext ctx, String clsName) {
+        this(ctx, ctx.typeId(clsName), PortableContext.typeName(clsName));
+    }
+
+    /**
+     * @param typeId Type ID.
+     * @param ctx Portable context.
+     */
+    public PortableBuilderImpl(PortableContext ctx, int typeId) {
+        this(ctx, typeId, null);
+    }
+
+    /**
+     * @param typeName Type name.
+     * @param ctx Context.
+     * @param typeId Type id.
+     */
+    public PortableBuilderImpl(PortableContext ctx, int typeId, String typeName) {
+        this.typeId = typeId;
+        this.typeName = typeName;
+        this.ctx = ctx;
+
+        start = -1;
+        reader = null;
+        hdrLen = DFLT_HDR_LEN;
+
+        readCache = Collections.emptyMap();
+    }
+
+    /**
+     * @param obj Object to wrap.
+     */
+    public PortableBuilderImpl(PortableObjectImpl obj) {
+        this(new PortableBuilderReader(obj), obj.start());
+
+        reader.registerObject(this);
+    }
+
+    /**
+     * @param reader ctx
+     * @param start Start.
+     */
+    PortableBuilderImpl(PortableBuilderReader reader, int start) {
+        this.reader = reader;
+        this.start = start;
+
+        int typeId = reader.readIntAbsolute(start + TYPE_ID_POS);
+        ctx = reader.portableContext();
+        hashCode = reader.readIntAbsolute(start + HASH_CODE_POS);
+
+        if (typeId == UNREGISTERED_TYPE_ID) {
+            int mark = reader.position();
+
+            reader.position(start + CLS_NAME_POS);
+
+            clsNameToWrite = reader.readString();
+
+            Class cls;
+
+            try {
+                // TODO: IGNITE-1272 - Is class loader needed here?
+                cls = U.forName(clsNameToWrite, null);
+            }
+            catch (ClassNotFoundException e) {
+                throw new PortableInvalidClassException("Failed to load the class: " + clsNameToWrite, e);
+            }
+
+            this.typeId = ctx.descriptorForClass(cls).typeId();
+
+            registeredType = false;
+
+            hdrLen = reader.position() - mark;
+
+            reader.position(mark);
+        }
+        else {
+            this.typeId = typeId;
+            hdrLen = DFLT_HDR_LEN;
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public PortableObject build() {
+        try (PortableWriterExImpl writer = new PortableWriterExImpl(ctx, 0, typeId, false)) {
+
+            PortableBuilderSerializer serializationCtx = new PortableBuilderSerializer();
+
+            serializationCtx.registerObjectWriting(this, 0);
+
+            serializeTo(writer, serializationCtx);
+
+            byte[] arr = writer.array();
+
+            return new PortableObjectImpl(ctx, arr, 0);
+        }
+    }
+
+    /**
+     * @param writer Writer.
+     * @param serializer Serializer.
+     */
+    void serializeTo(PortableWriterExImpl writer, PortableBuilderSerializer serializer) {
+        writer.doWriteByte(GridPortableMarshaller.OBJ);
+        writer.doWriteBoolean(true);
+        writer.doWriteInt(registeredType ? typeId : UNREGISTERED_TYPE_ID);
+        writer.doWriteInt(hashCode);
+
+        // Length and raw offset.
+        writer.reserve(8);
+
+        if (!registeredType)
+            writer.writeString(clsNameToWrite);
+
+        Set<Integer> remainsFlds = null;
+
+        if (reader != null) {
+            Map<Integer, Object> assignedFldsById;
+
+            if (assignedVals != null) {
+                assignedFldsById = U.newHashMap(assignedVals.size());
+
+                for (Map.Entry<String, Object> entry : assignedVals.entrySet()) {
+                    int fldId = ctx.fieldId(typeId, entry.getKey());
+
+                    assignedFldsById.put(fldId, entry.getValue());
+                }
+
+                remainsFlds = assignedFldsById.keySet();
+            }
+            else
+                assignedFldsById = Collections.emptyMap();
+
+            int rawOff = start + reader.readIntAbsolute(start + RAW_DATA_OFF_POS);
+
+            reader.position(start + hdrLen);
+
+            int cpStart = -1;
+
+            while (reader.position() < rawOff) {
+                int fldId = reader.readInt();
+
+                int len = reader.readInt();
+
+                if (assignedFldsById.containsKey(fldId)) {
+                    if (cpStart >= 0) {
+                        writer.write(reader.array(), cpStart, reader.position() - 4 - 4 - cpStart);
+
+                        cpStart = -1;
+                    }
+
+                    Object assignedVal = assignedFldsById.remove(fldId);
+
+                    reader.skip(len);
+
+                    if (assignedVal != REMOVED_FIELD_MARKER) {
+                        writer.writeInt(fldId);
+
+                        int lenPos = writer.reserveAndMark(4);
+
+                        serializer.writeValue(writer, assignedVal);
+
+                        writer.writeDelta(lenPos);
+                    }
+                }
+                else {
+                    int type = len != 0 ? reader.readByte(0) : 0;
+
+                    if (len != 0 && !PortableUtils.isPlainArrayType(type) && PortableUtils.isPlainType(type)) {
+                        if (cpStart < 0)
+                            cpStart = reader.position() - 4 - 4;
+
+                        reader.skip(len);
+                    }
+                    else {
+                        if (cpStart >= 0) {
+                            writer.write(reader.array(), cpStart, reader.position() - 4 - cpStart);
+
+                            cpStart = -1;
+                        }
+                        else
+                            writer.writeInt(fldId);
+
+                        Object val;
+
+                        if (len == 0)
+                            val = null;
+                        else if (readCache == null) {
+                            int savedPos = reader.position();
+
+                            val = reader.parseValue();
+
+                            assert reader.position() == savedPos + len;
+                        }
+                        else {
+                            val = readCache.get(fldId);
+
+                            reader.skip(len);
+                        }
+
+                        int lenPos = writer.reserveAndMark(4);
+
+                        serializer.writeValue(writer, val);
+
+                        writer.writeDelta(lenPos);
+                    }
+                }
+            }
+
+            if (cpStart >= 0)
+                writer.write(reader.array(), cpStart, reader.position() - cpStart);
+        }
+
+        if (assignedVals != null && (remainsFlds == null || !remainsFlds.isEmpty())) {
+            boolean metadataEnabled = ctx.isMetaDataEnabled(typeId);
+
+            PortableMetadata metadata = null;
+
+            if (metadataEnabled)
+                metadata = ctx.metaData(typeId);
+
+            Map<String, String> newFldsMetadata = null;
+
+            for (Map.Entry<String, Object> entry : assignedVals.entrySet()) {
+                Object val = entry.getValue();
+
+                if (val == REMOVED_FIELD_MARKER)
+                    continue;
+
+                String name = entry.getKey();
+
+                int fldId = ctx.fieldId(typeId, name);
+
+                if (remainsFlds != null && !remainsFlds.contains(fldId))
+                    continue;
+
+                writer.writeInt(fldId);
+
+                int lenPos = writer.reserveAndMark(4);
+
+                serializer.writeValue(writer, val);
+
+                writer.writeDelta(lenPos);
+
+                if (metadataEnabled) {
+                    String oldFldTypeName = metadata == null ? null : metadata.fieldTypeName(name);
+
+                    String newFldTypeName;
+
+                    if (val instanceof PortableValueWithType)
+                        newFldTypeName = ((PortableValueWithType)val).typeName();
+                    else {
+                        byte type = PortableUtils.typeByClass(val.getClass());
+
+                        newFldTypeName = CacheObjectPortableProcessorImpl.fieldTypeName(type);
+                    }
+
+                    if (oldFldTypeName == null) {
+                        // It's a new field, we have to add it to metadata.
+
+                        if (newFldsMetadata == null)
+                            newFldsMetadata = new HashMap<>();
+
+                        newFldsMetadata.put(name, newFldTypeName);
+                    }
+                    else {
+                        if (!"Object".equals(oldFldTypeName) && !oldFldTypeName.equals(newFldTypeName)) {
+                            throw new PortableException(
+                                "Wrong value has been set [" +
+                                    "typeName=" + (typeName == null ? metadata.typeName() : typeName) +
+                                    ", fieldName=" + name +
+                                    ", fieldType=" + oldFldTypeName +
+                                    ", assignedValueType=" + newFldTypeName +
+                                    ", assignedValue=" + (((PortableValueWithType)val).value()) + ']'
+                            );
+                        }
+                    }
+                }
+            }
+
+            if (newFldsMetadata != null) {
+                String typeName = this.typeName;
+
+                if (typeName == null)
+                    typeName = metadata.typeName();
+
+                ctx.updateMetaData(typeId, typeName, newFldsMetadata);
+            }
+        }
+
+        writer.writeRawOffsetIfNeeded();
+
+        if (reader != null) {
+            int rawOff = reader.readIntAbsolute(start + RAW_DATA_OFF_POS);
+            int len = reader.readIntAbsolute(start + TOTAL_LEN_POS);
+
+            if (rawOff < len)
+                writer.write(reader.array(), rawOff, len - rawOff);
+        }
+
+        writer.writeLength();
+    }
+
+    /** {@inheritDoc} */
+    @Override public PortableBuilderImpl hashCode(int hashCode) {
+        this.hashCode = hashCode;
+
+        return this;
+    }
+
+    /**
+     *
+     */
+    private void ensureReadCacheInit() {
+        if (readCache == null) {
+            Map<Integer, Object> readCache = new HashMap<>();
+
+            int pos = start + hdrLen;
+            int end = start + reader.readIntAbsolute(start + RAW_DATA_OFF_POS);
+
+            while (pos < end) {
+                int fieldId = reader.readIntAbsolute(pos);
+
+                pos += 4;
+
+                int len = reader.readIntAbsolute(pos);
+
+                pos += 4;
+
+                Object val = reader.getValueQuickly(pos, len);
+
+                readCache.put(fieldId, val);
+
+                pos += len;
+            }
+
+            this.readCache = readCache;
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public <F> F getField(String name) {
+        Object val;
+
+        if (assignedVals != null && assignedVals.containsKey(name)) {
+            val = assignedVals.get(name);
+
+            if (val == REMOVED_FIELD_MARKER)
+                return null;
+        }
+        else {
+            ensureReadCacheInit();
+
+            int fldId = ctx.fieldId(typeId, name);
+
+            val = readCache.get(fldId);
+        }
+
+        return (F)PortableUtils.unwrapLazy(val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public PortableBuilder setField(String name, Object val) {
+        GridArgumentCheck.notNull(val, name);
+
+        if (assignedVals == null)
+            assignedVals = new LinkedHashMap<>();
+
+        Object oldVal = assignedVals.put(name, val);
+
+        if (oldVal instanceof PortableValueWithType) {
+            ((PortableValueWithType)oldVal).value(val);
+
+            assignedVals.put(name, oldVal);
+        }
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T> PortableBuilder setField(String name, @Nullable T val, Class<? super T> type) {
+        if (assignedVals == null)
+            assignedVals = new LinkedHashMap<>();
+
+        //int fldId = ctx.fieldId(typeId, fldName);
+
+        assignedVals.put(name, new PortableValueWithType(PortableUtils.typeByClass(type), val));
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public PortableBuilder setField(String name, @Nullable PortableBuilder builder) {
+        if (builder == null)
+            return setField(name, null, Object.class);
+        else
+            return setField(name, (Object)builder);
+    }
+
+    /**
+     * Removes field from portable object.
+     *
+     * @param name Field name.
+     * @return {@code this} instance for chaining.
+     */
+    @Override public PortableBuilderImpl removeField(String name) {
+        if (assignedVals == null)
+            assignedVals = new LinkedHashMap<>();
+
+        assignedVals.put(name, REMOVED_FIELD_MARKER);
+
+        return this;
+    }
+
+    /**
+     * Creates builder initialized by specified portable object.
+     *
+     * @param obj Portable object to initialize builder.
+     * @return New builder.
+     */
+    public static PortableBuilderImpl wrap(PortableObject obj) {
+        PortableObjectImpl heapObj;
+
+        if (obj instanceof PortableObjectOffheapImpl)
+            heapObj = (PortableObjectImpl)((PortableObjectOffheapImpl)obj).heapCopy();
+        else
+            heapObj = (PortableObjectImpl)obj;
+
+        return new PortableBuilderImpl(heapObj);
+    }
+
+    /**
+     * @return Object start position in source array.
+     */
+    int start() {
+        return start;
+    }
+
+    /**
+     * @return Object type id.
+     */
+    public int typeId() {
+        return typeId;
+    }
+}
\ No newline at end of file


[4/4] ignite git commit: ignite-1273: fixed cyclic references processing by PortableMarshaller and ability to modify array fields returned by PortableBuilder

Posted by sb...@apache.org.
ignite-1273: fixed cyclic references processing by PortableMarshaller and ability to modify array fields returned by PortableBuilder


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/6ac9557e
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/6ac9557e
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/6ac9557e

Branch: refs/heads/master
Commit: 6ac9557ef71b7745eff90bcf15a4f7a958fcfa6b
Parents: 8bd8644
Author: Denis Magda <dm...@gridgain.com>
Authored: Thu Sep 3 08:30:36 2015 +0300
Committer: Denis Magda <dm...@gridgain.com>
Committed: Thu Sep 3 08:30:36 2015 +0300

----------------------------------------------------------------------
 .../portable/GridPortableMarshaller.java        |  44 +-
 .../portable/PortableAbstractLazyValue.java     |  57 --
 .../internal/portable/PortableBuilderEnum.java  | 114 ---
 .../internal/portable/PortableBuilderImpl.java  | 531 ------------
 .../portable/PortableBuilderReader.java         | 776 ------------------
 .../PortableBuilderSerializationAware.java      |  29 -
 .../portable/PortableBuilderSerializer.java     | 211 -----
 .../portable/PortableClassDescriptor.java       |  57 +-
 .../internal/portable/PortableContext.java      |   6 +-
 .../portable/PortableEnumArrayLazyValue.java    | 112 ---
 .../portable/PortableLazyArrayList.java         | 159 ----
 .../portable/PortableLazyLinkedList.java        | 215 -----
 .../internal/portable/PortableLazyMap.java      | 218 -----
 .../internal/portable/PortableLazyMapEntry.java |  66 --
 .../internal/portable/PortableLazySet.java      |  89 ---
 .../internal/portable/PortableLazyValue.java    |  28 -
 .../portable/PortableObjectArrayLazyValue.java  |  89 ---
 .../portable/PortablePlainLazyValue.java        |  47 --
 .../portable/PortablePlainPortableObject.java   |  50 --
 .../internal/portable/PortableReaderExImpl.java | 154 +++-
 .../ignite/internal/portable/PortableUtils.java |  11 +
 .../portable/PortableValueWithType.java         |  74 --
 .../internal/portable/PortableWriterExImpl.java | 159 +++-
 .../builder/PortableAbstractLazyValue.java      |  57 ++
 .../portable/builder/PortableBuilderEnum.java   | 116 +++
 .../portable/builder/PortableBuilderImpl.java   | 537 +++++++++++++
 .../portable/builder/PortableBuilderReader.java | 800 +++++++++++++++++++
 .../PortableBuilderSerializationAware.java      |  31 +
 .../builder/PortableBuilderSerializer.java      | 214 +++++
 .../builder/PortableEnumArrayLazyValue.java     | 114 +++
 .../portable/builder/PortableLazyArrayList.java | 166 ++++
 .../builder/PortableLazyLinkedList.java         | 217 +++++
 .../portable/builder/PortableLazyMap.java       | 220 +++++
 .../portable/builder/PortableLazyMapEntry.java  |  68 ++
 .../portable/builder/PortableLazySet.java       |  92 +++
 .../portable/builder/PortableLazyValue.java     |  28 +
 .../builder/PortableModifiableLazyValue.java    |  52 ++
 .../builder/PortableObjectArrayLazyValue.java   |  91 +++
 .../builder/PortablePlainLazyValue.java         |  49 ++
 .../builder/PortablePlainPortableObject.java    |  53 ++
 .../portable/builder/PortableValueWithType.java |  75 ++
 .../internal/portable/builder/package-info.java |  22 +
 .../CacheObjectPortableProcessorImpl.java       |   2 +-
 .../resources/META-INF/classnames.properties    |   2 +-
 .../GridPortableBuilderAdditionalSelfTest.java  | 232 +++++-
 .../portable/GridPortableBuilderSelfTest.java   |   1 +
 .../GridPortableMarshallerSelfTest.java         |  72 +-
 .../GridPortableMetaDataDisabledSelfTest.java   |  17 +
 .../portable/GridPortableMetaDataSelfTest.java  |  17 +
 .../mutabletest/GridPortableTestClasses.java    |  38 +-
 ...ClientNodePortableMetadataMultinodeTest.java |  11 +
 51 files changed, 3687 insertions(+), 3003 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/GridPortableMarshaller.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/GridPortableMarshaller.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/GridPortableMarshaller.java
index 3b2357e..c7a9e6f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/GridPortableMarshaller.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/GridPortableMarshaller.java
@@ -142,67 +142,67 @@ public class GridPortableMarshaller {
     public static final byte OBJ = (byte)103;
 
     /** */
-    static final byte USER_SET = -1;
+    public static final byte USER_SET = -1;
 
     /** */
-    static final byte USER_COL = 0;
+    public static final byte USER_COL = 0;
 
     /** */
-    static final byte ARR_LIST = 1;
+    public static final byte ARR_LIST = 1;
 
     /** */
-    static final byte LINKED_LIST = 2;
+    public static final byte LINKED_LIST = 2;
 
     /** */
-    static final byte HASH_SET = 3;
+    public static final byte HASH_SET = 3;
 
     /** */
-    static final byte LINKED_HASH_SET = 4;
+    public static final byte LINKED_HASH_SET = 4;
 
     /** */
-    static final byte TREE_SET = 5;
+    public static final byte TREE_SET = 5;
 
     /** */
-    static final byte CONC_SKIP_LIST_SET = 6;
+    public static final byte CONC_SKIP_LIST_SET = 6;
 
     /** */
-    static final byte HASH_MAP = 1;
+    public static final byte HASH_MAP = 1;
 
     /** */
-    static final byte LINKED_HASH_MAP = 2;
+    public static final byte LINKED_HASH_MAP = 2;
 
     /** */
-    static final byte TREE_MAP = 3;
+    public static final byte TREE_MAP = 3;
 
     /** */
-    static final byte CONC_HASH_MAP = 4;
+    public static final byte CONC_HASH_MAP = 4;
 
     /** */
-    static final byte PROPERTIES_MAP = 5;
+    public static final byte PROPERTIES_MAP = 5;
 
     /** */
-    static final int OBJECT_TYPE_ID = -1;
+    public static final int OBJECT_TYPE_ID = -1;
 
     /** */
-    static final int UNREGISTERED_TYPE_ID = 0;
+    public static final int UNREGISTERED_TYPE_ID = 0;
 
     /** */
-    static final int TYPE_ID_POS = 2;
+    public static final int TYPE_ID_POS = 2;
 
     /** */
-    static final int HASH_CODE_POS = 6;
+    public static final int HASH_CODE_POS = 6;
 
     /** */
-    static final int TOTAL_LEN_POS = 10;
+    public static final int TOTAL_LEN_POS = 10;
 
     /** */
-    static final byte RAW_DATA_OFF_POS = 14;
+    public static final byte RAW_DATA_OFF_POS = 14;
 
     /** */
-    static final int CLS_NAME_POS = 18;
+    public static final int CLS_NAME_POS = 18;
 
     /** */
-    static final byte DFLT_HDR_LEN = 18;
+    public static final byte DFLT_HDR_LEN = 18;
 
     /** */
     private final PortableContext ctx;
@@ -301,4 +301,4 @@ public class GridPortableMarshaller {
     public PortableContext context() {
         return ctx;
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableAbstractLazyValue.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableAbstractLazyValue.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableAbstractLazyValue.java
deleted file mode 100644
index 2b1c4b7..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableAbstractLazyValue.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-/**
- *
- */
-abstract class PortableAbstractLazyValue implements PortableLazyValue {
-    /** */
-    protected Object val;
-
-    /** */
-    protected final PortableBuilderReader reader;
-
-    /** */
-    protected final int valOff;
-
-    /**
-     * @param reader Reader.
-     * @param valOff Value.
-     */
-    protected PortableAbstractLazyValue(PortableBuilderReader reader, int valOff) {
-        this.reader = reader;
-        this.valOff = valOff;
-    }
-
-    /**
-     * @return Value.
-     */
-    protected abstract Object init();
-
-    /** {@inheritDoc} */
-    @Override public Object value() {
-        if (val == null) {
-            val = init();
-
-            assert val != null;
-        }
-
-        return val;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderEnum.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderEnum.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderEnum.java
deleted file mode 100644
index b6ace99..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderEnum.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.portable.PortableInvalidClassException;
-
-/**
- *
- */
-public class PortableBuilderEnum implements PortableBuilderSerializationAware {
-    /** */
-    private final int ordinal;
-
-    /** */
-    private final int typeId;
-
-    /** */
-    private final String clsName;
-
-    /**
-     * @param typeId Type ID.
-     * @param anEnum Enum instance.
-     */
-    public PortableBuilderEnum(int typeId, Enum anEnum) {
-        ordinal = anEnum.ordinal();
-        this.typeId = typeId;
-        clsName = null;
-    }
-
-    /**
-     * @param reader PortableBuilderReader.
-     */
-    public PortableBuilderEnum(PortableBuilderReader reader) {
-        int typeId = reader.readInt();
-
-        if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) {
-            clsName = reader.readString();
-
-            Class cls;
-
-            try {
-                // TODO: IGNITE-1272 - Is class loader needed here?
-                cls = U.forName(reader.readString(), null);
-            }
-            catch (ClassNotFoundException e) {
-                throw new PortableInvalidClassException("Failed to load the class: " + clsName, e);
-            }
-
-            this.typeId = reader.portableContext().descriptorForClass(cls).typeId();
-        }
-        else {
-            this.typeId = typeId;
-            this.clsName = null;
-        }
-
-        ordinal = reader.readInt();
-    }
-
-    /**
-     * @return Ordinal.
-     */
-    public int getOrdinal() {
-        return ordinal;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
-        writer.writeByte(GridPortableMarshaller.ENUM);
-
-        if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) {
-            writer.writeInt(GridPortableMarshaller.UNREGISTERED_TYPE_ID);
-            writer.writeString(clsName);
-        }
-        else
-            writer.writeInt(typeId);
-
-        writer.writeInt(ordinal);
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean equals(Object o) {
-        if (o == null || getClass() != o.getClass())
-            return false;
-
-        PortableBuilderEnum that = (PortableBuilderEnum)o;
-
-        return ordinal == that.ordinal && typeId == that.typeId;
-    }
-
-    /** {@inheritDoc} */
-    @Override public int hashCode() {
-        int result = ordinal;
-
-        result = 31 * result + typeId;
-
-        return result;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderImpl.java
deleted file mode 100644
index dac199a..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderImpl.java
+++ /dev/null
@@ -1,531 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-import org.apache.ignite.internal.processors.cache.portable.CacheObjectPortableProcessorImpl;
-import org.apache.ignite.internal.util.GridArgumentCheck;
-import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.portable.PortableBuilder;
-import org.apache.ignite.portable.PortableException;
-import org.apache.ignite.portable.PortableInvalidClassException;
-import org.apache.ignite.portable.PortableMetadata;
-import org.apache.ignite.portable.PortableObject;
-import org.jetbrains.annotations.Nullable;
-
-import static org.apache.ignite.internal.portable.GridPortableMarshaller.CLS_NAME_POS;
-import static org.apache.ignite.internal.portable.GridPortableMarshaller.DFLT_HDR_LEN;
-import static org.apache.ignite.internal.portable.GridPortableMarshaller.HASH_CODE_POS;
-import static org.apache.ignite.internal.portable.GridPortableMarshaller.RAW_DATA_OFF_POS;
-import static org.apache.ignite.internal.portable.GridPortableMarshaller.TOTAL_LEN_POS;
-import static org.apache.ignite.internal.portable.GridPortableMarshaller.TYPE_ID_POS;
-import static org.apache.ignite.internal.portable.GridPortableMarshaller.UNREGISTERED_TYPE_ID;
-
-/**
- *
- */
-public class PortableBuilderImpl implements PortableBuilder {
-    /** */
-    private static final Object REMOVED_FIELD_MARKER = new Object();
-
-    /** */
-    private final PortableContext ctx;
-
-    /** */
-    private final int typeId;
-
-    /** May be null. */
-    private String typeName;
-
-    /** May be null. */
-    private String clsNameToWrite;
-
-    /** */
-    private boolean registeredType = true;
-
-    /** */
-    private Map<String, Object> assignedVals;
-
-    /** */
-    private Map<Integer, Object> readCache;
-
-    /** Position of object in source array, or -1 if object is not created from PortableObject. */
-    private final int start;
-
-    /** Total header length */
-    private final int hdrLen;
-
-    /**
-     * Context of PortableObject reading process. Or {@code null} if object is not created from PortableObject.
-     */
-    private final PortableBuilderReader reader;
-
-    /** */
-    private int hashCode;
-
-    /**
-     * @param clsName Class name.
-     * @param ctx Portable context.
-     */
-    public PortableBuilderImpl(PortableContext ctx, String clsName) {
-        this(ctx, ctx.typeId(clsName), PortableContext.typeName(clsName));
-    }
-
-    /**
-     * @param typeId Type ID.
-     * @param ctx Portable context.
-     */
-    public PortableBuilderImpl(PortableContext ctx, int typeId) {
-        this(ctx, typeId, null);
-    }
-
-    /**
-     * @param typeName Type name.
-     * @param ctx Context.
-     * @param typeId Type id.
-     */
-    public PortableBuilderImpl(PortableContext ctx, int typeId, String typeName) {
-        this.typeId = typeId;
-        this.typeName = typeName;
-        this.ctx = ctx;
-
-        start = -1;
-        reader = null;
-        hdrLen = DFLT_HDR_LEN;
-
-        readCache = Collections.emptyMap();
-    }
-
-    /**
-     * @param obj Object to wrap.
-     */
-    public PortableBuilderImpl(PortableObjectImpl obj) {
-        this(new PortableBuilderReader(obj), obj.start());
-
-        reader.registerObject(this);
-    }
-
-    /**
-     * @param reader ctx
-     * @param start Start.
-     */
-    PortableBuilderImpl(PortableBuilderReader reader, int start) {
-        this.reader = reader;
-        this.start = start;
-
-        int typeId = reader.readIntAbsolute(start + TYPE_ID_POS);
-        ctx = reader.portableContext();
-        hashCode = reader.readIntAbsolute(start + HASH_CODE_POS);
-
-        if (typeId == UNREGISTERED_TYPE_ID) {
-            int mark = reader.position();
-
-            reader.position(start + CLS_NAME_POS);
-
-            clsNameToWrite = reader.readString();
-
-            Class cls;
-
-            try {
-                // TODO: IGNITE-1272 - Is class loader needed here?
-                cls = U.forName(clsNameToWrite, null);
-            }
-            catch (ClassNotFoundException e) {
-                throw new PortableInvalidClassException("Failed to load the class: " + clsNameToWrite, e);
-            }
-
-            this.typeId = ctx.descriptorForClass(cls).typeId();
-
-            registeredType = false;
-
-            hdrLen = reader.position() - mark;
-
-            reader.position(mark);
-        }
-        else {
-            this.typeId = typeId;
-            hdrLen = DFLT_HDR_LEN;
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override public PortableObject build() {
-        try (PortableWriterExImpl writer = new PortableWriterExImpl(ctx, 0, typeId, false)) {
-
-            PortableBuilderSerializer serializationCtx = new PortableBuilderSerializer();
-
-            serializationCtx.registerObjectWriting(this, 0);
-
-            serializeTo(writer, serializationCtx);
-
-            byte[] arr = writer.array();
-
-            return new PortableObjectImpl(ctx, arr, 0);
-        }
-    }
-
-    /**
-     * @param writer Writer.
-     * @param serializer Serializer.
-     */
-    void serializeTo(PortableWriterExImpl writer, PortableBuilderSerializer serializer) {
-        writer.doWriteByte(GridPortableMarshaller.OBJ);
-        writer.doWriteBoolean(true);
-        writer.doWriteInt(registeredType ? typeId : UNREGISTERED_TYPE_ID);
-        writer.doWriteInt(hashCode);
-
-        // Length and raw offset.
-        writer.reserve(8);
-
-        if (!registeredType)
-            writer.writeString(clsNameToWrite);
-
-
-        Set<Integer> remainsFlds = null;
-
-        if (reader != null) {
-            Map<Integer, Object> assignedFldsById;
-
-            if (assignedVals != null) {
-                assignedFldsById = U.newHashMap(assignedVals.size());
-
-                for (Map.Entry<String, Object> entry : assignedVals.entrySet()) {
-                    int fldId = ctx.fieldId(typeId, entry.getKey());
-
-                    assignedFldsById.put(fldId, entry.getValue());
-                }
-
-                remainsFlds = assignedFldsById.keySet();
-            }
-            else
-                assignedFldsById = Collections.emptyMap();
-
-            int rawOff = start + reader.readIntAbsolute(start + RAW_DATA_OFF_POS);
-
-            reader.position(start + hdrLen);
-
-            int cpStart = -1;
-
-            while (reader.position() < rawOff) {
-                int fldId = reader.readInt();
-
-                int len = reader.readInt();
-
-                if (assignedFldsById.containsKey(fldId)) {
-                    if (cpStart >= 0) {
-                        writer.write(reader.array(), cpStart, reader.position() - 4 - 4 - cpStart);
-
-                        cpStart = -1;
-                    }
-
-                    Object assignedVal = assignedFldsById.remove(fldId);
-
-                    reader.skip(len);
-
-                    if (assignedVal != REMOVED_FIELD_MARKER) {
-                        writer.writeInt(fldId);
-
-                        int lenPos = writer.reserveAndMark(4);
-
-                        serializer.writeValue(writer, assignedVal);
-
-                        writer.writeDelta(lenPos);
-                    }
-                }
-                else {
-                    if (len != 0 && PortableUtils.isPlainType(reader.readByte(0))) {
-                        if (cpStart < 0)
-                            cpStart = reader.position() - 4 - 4;
-
-                        reader.skip(len);
-                    }
-                    else {
-                        if (cpStart >= 0) {
-                            writer.write(reader.array(), cpStart, reader.position() - 4 - cpStart);
-
-                            cpStart = -1;
-                        }
-                        else
-                            writer.writeInt(fldId);
-
-                        Object val;
-
-                        if (len == 0)
-                            val = null;
-                        else if (readCache == null) {
-                            int savedPos = reader.position();
-
-                            val = reader.parseValue();
-
-                            assert reader.position() == savedPos + len;
-                        }
-                        else {
-                            val = readCache.get(fldId);
-
-                            reader.skip(len);
-                        }
-
-                        int lenPos = writer.reserveAndMark(4);
-
-                        serializer.writeValue(writer, val);
-
-                        writer.writeDelta(lenPos);
-                    }
-                }
-            }
-
-            if (cpStart >= 0)
-                writer.write(reader.array(), cpStart, reader.position() - cpStart);
-        }
-
-        if (assignedVals != null && (remainsFlds == null || !remainsFlds.isEmpty())) {
-            boolean metadataEnabled = ctx.isMetaDataEnabled(typeId);
-
-            PortableMetadata metadata = null;
-
-            if (metadataEnabled)
-                metadata = ctx.metaData(typeId);
-
-            Map<String, String> newFldsMetadata = null;
-
-            for (Map.Entry<String, Object> entry : assignedVals.entrySet()) {
-                Object val = entry.getValue();
-
-                if (val == REMOVED_FIELD_MARKER)
-                    continue;
-
-                String name = entry.getKey();
-
-                int fldId = ctx.fieldId(typeId, name);
-
-                if (remainsFlds != null && !remainsFlds.contains(fldId))
-                    continue;
-
-                writer.writeInt(fldId);
-
-                int lenPos = writer.reserveAndMark(4);
-
-                serializer.writeValue(writer, val);
-
-                writer.writeDelta(lenPos);
-
-                if (metadataEnabled) {
-                    String oldFldTypeName = metadata == null ? null : metadata.fieldTypeName(name);
-
-                    String newFldTypeName;
-
-                    if (val instanceof PortableValueWithType)
-                        newFldTypeName = ((PortableValueWithType)val).typeName();
-                    else {
-                        byte type = PortableUtils.typeByClass(val.getClass());
-
-                        newFldTypeName = CacheObjectPortableProcessorImpl.fieldTypeName(type);
-                    }
-
-                    if (oldFldTypeName == null) {
-                        // It's a new field, we have to add it to metadata.
-
-                        if (newFldsMetadata == null)
-                            newFldsMetadata = new HashMap<>();
-
-                        newFldsMetadata.put(name, newFldTypeName);
-                    }
-                    else {
-                        if (!"Object".equals(oldFldTypeName) && !oldFldTypeName.equals(newFldTypeName)) {
-                            throw new PortableException(
-                                "Wrong value has been set [" +
-                                    "typeName=" + (typeName == null ? metadata.typeName() : typeName) +
-                                    ", fieldName=" + name +
-                                    ", fieldType=" + oldFldTypeName +
-                                    ", assignedValueType=" + newFldTypeName +
-                                    ", assignedValue=" + (((PortableValueWithType)val).value()) + ']'
-                            );
-                        }
-                    }
-                }
-            }
-
-            if (newFldsMetadata != null) {
-                String typeName = this.typeName;
-
-                if (typeName == null)
-                    typeName = metadata.typeName();
-
-                ctx.updateMetaData(typeId, typeName, newFldsMetadata);
-            }
-        }
-
-        writer.writeRawOffsetIfNeeded();
-
-        if (reader != null) {
-            int rawOff = reader.readIntAbsolute(start + RAW_DATA_OFF_POS);
-            int len = reader.readIntAbsolute(start + TOTAL_LEN_POS);
-
-            if (rawOff < len)
-                writer.write(reader.array(), rawOff, len - rawOff);
-        }
-
-        writer.writeLength();
-    }
-
-    /** {@inheritDoc} */
-    @Override public PortableBuilderImpl hashCode(int hashCode) {
-        this.hashCode = hashCode;
-
-        return this;
-    }
-
-    /**
-     *
-     */
-    private void ensureReadCacheInit() {
-        if (readCache == null) {
-            Map<Integer, Object> readCache = new HashMap<>();
-
-            int pos = start + hdrLen;
-            int end = start + reader.readIntAbsolute(start + RAW_DATA_OFF_POS);
-
-            while (pos < end) {
-                int fieldId = reader.readIntAbsolute(pos);
-
-                pos += 4;
-
-                int len = reader.readIntAbsolute(pos);
-
-                pos += 4;
-
-                Object val = reader.getValueQuickly(pos, len);
-
-                readCache.put(fieldId, val);
-
-                pos += len;
-            }
-
-            this.readCache = readCache;
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override public <F> F getField(String name) {
-        Object val;
-
-        if (assignedVals != null && assignedVals.containsKey(name)) {
-            val = assignedVals.get(name);
-
-            if (val == REMOVED_FIELD_MARKER)
-                return null;
-        }
-        else {
-            ensureReadCacheInit();
-
-            int fldId = ctx.fieldId(typeId, name);
-
-            val = readCache.get(fldId);
-        }
-
-        return (F)PortableUtils.unwrapLazy(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public PortableBuilder setField(String name, Object val) {
-        GridArgumentCheck.notNull(val, "val");
-
-        if (assignedVals == null)
-            assignedVals = new LinkedHashMap<>();
-
-        Object oldVal = assignedVals.put(name, val);
-
-        if (oldVal instanceof PortableValueWithType) {
-            ((PortableValueWithType)oldVal).value(val);
-
-            assignedVals.put(name, oldVal);
-        }
-
-        return this;
-    }
-
-    /** {@inheritDoc} */
-    @Override public <T> PortableBuilder setField(String name, @Nullable T val, Class<? super T> type) {
-        if (assignedVals == null)
-            assignedVals = new LinkedHashMap<>();
-
-        //int fldId = ctx.fieldId(typeId, fldName);
-
-        assignedVals.put(name, new PortableValueWithType(PortableUtils.typeByClass(type), val));
-
-        return this;
-    }
-
-    /** {@inheritDoc} */
-    @Override public PortableBuilder setField(String name, @Nullable PortableBuilder builder) {
-        if (builder == null)
-            return setField(name, null, Object.class);
-        else
-            return setField(name, (Object)builder);
-    }
-
-    /**
-     * Removes field from portable object.
-     *
-     * @param name Field name.
-     * @return {@code this} instance for chaining.
-     */
-    @Override public PortableBuilderImpl removeField(String name) {
-        if (assignedVals == null)
-            assignedVals = new LinkedHashMap<>();
-
-        assignedVals.put(name, REMOVED_FIELD_MARKER);
-
-        return this;
-    }
-
-    /**
-     * Creates builder initialized by specified portable object.
-     *
-     * @param obj Portable object to initialize builder.
-     * @return New builder.
-     */
-    public static PortableBuilderImpl wrap(PortableObject obj) {
-        PortableObjectImpl heapObj;
-
-        if (obj instanceof PortableObjectOffheapImpl)
-            heapObj = (PortableObjectImpl)((PortableObjectOffheapImpl)obj).heapCopy();
-        else
-            heapObj = (PortableObjectImpl)obj;
-
-        return new PortableBuilderImpl(heapObj);
-    }
-
-    /**
-     * @return Object start position in source array.
-     */
-    int start() {
-        return start;
-    }
-
-    /**
-     * @return Object type id.
-     */
-    int typeId() {
-        return typeId;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderReader.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderReader.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderReader.java
deleted file mode 100644
index 30b31f0..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderReader.java
+++ /dev/null
@@ -1,776 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-import java.sql.Timestamp;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import org.apache.ignite.portable.PortableException;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.apache.ignite.internal.portable.GridPortableMarshaller.NULL;
-import static org.apache.ignite.internal.portable.GridPortableMarshaller.STRING;
-
-/**
- *
- */
-class PortableBuilderReader {
-    /** */
-    private static final PortablePrimitives PRIM = PortablePrimitives.get();
-
-    /** */
-    private final Map<Integer, PortableBuilderImpl> objMap = new HashMap<>();
-
-    /** */
-    private final PortableContext ctx;
-
-    /** */
-    private final PortableReaderExImpl reader;
-
-    /** */
-    private byte[] arr;
-
-    /** */
-    private int pos;
-
-    /**
-     * @param objImpl Portable object
-     */
-    PortableBuilderReader(PortableObjectImpl objImpl) {
-        ctx = objImpl.context();
-        arr = objImpl.array();
-        pos = objImpl.start();
-
-        // TODO: IGNITE-1272 - Is class loader needed here?
-        reader = new PortableReaderExImpl(portableContext(), arr, pos, null);
-    }
-
-    /**
-     * @return Portable context.
-     */
-    public PortableContext portableContext() {
-        return ctx;
-    }
-
-    /**
-     * @param obj Mutable portable object.
-     */
-    public void registerObject(PortableBuilderImpl obj) {
-        objMap.put(obj.start(), obj);
-    }
-
-    /**
-     * @return Read int value.
-     */
-    public int readInt() {
-        int res = readInt(0);
-
-        pos += 4;
-
-        return res;
-    }
-
-    /**
-     * @return Read int value.
-     */
-    public byte readByte() {
-        return arr[pos++];
-    }
-
-    /**
-     * @return Read boolean value.
-     */
-    public boolean readBoolean() {
-        return readByte() == 1;
-    }
-
-    /**
-     * @return Read int value.
-     */
-    public byte readByte(int off) {
-        return arr[pos + off];
-    }
-
-    /**
-     * @param off Offset related to {@link #pos}
-     * @return Read int value.
-     */
-    public int readInt(int off) {
-        return PRIM.readInt(arr, pos + off);
-    }
-
-    /**
-     * @param pos Position in the source array.
-     * @return Read int value.
-     */
-    public int readIntAbsolute(int pos) {
-        return PRIM.readInt(arr, pos);
-    }
-
-    /**
-     * @return Read length of array.
-     */
-    public int readLength() {
-        return PRIM.readInt(arr, pos);
-    }
-
-    /**
-     * Read string length.
-     *
-     * @return String length.
-     */
-    public int readStringLength() {
-        boolean utf = PRIM.readBoolean(arr, pos);
-
-        int arrLen = PRIM.readInt(arr, pos + 1);
-
-        return 1 + (utf ? arrLen : arrLen << 1);
-    }
-
-    /**
-     * Reads string.
-     *
-     * @return String.
-     */
-    public String readString() {
-        byte flag = readByte();
-
-        if (flag == NULL)
-            return null;
-
-        if (flag != STRING)
-            throw new PortableException("Failed to deserialize String.");
-
-        boolean convert = readBoolean();
-        int len = readInt();
-
-        String str;
-
-        if (convert) {
-            str = new String(arr, pos, len, UTF_8);
-
-            pos += len;
-        }
-        else {
-            str = String.valueOf(PRIM.readCharArray(arr, pos, len));
-
-            pos += len << 1;
-        }
-
-        return str;
-    }
-
-    /**
-     *
-     */
-    public void skipValue() {
-        byte type = arr[pos++];
-
-        int len;
-
-        switch (type) {
-            case GridPortableMarshaller.NULL:
-                return;
-
-            case GridPortableMarshaller.OBJ:
-                pos += readInt(GridPortableMarshaller.TOTAL_LEN_POS - 1) - 1;
-
-                return;
-
-            case GridPortableMarshaller.BOOLEAN:
-            case GridPortableMarshaller.BYTE:
-                len = 1;
-                break;
-
-            case GridPortableMarshaller.CHAR:
-            case GridPortableMarshaller.SHORT:
-                len = 2;
-
-                break;
-
-            case GridPortableMarshaller.HANDLE:
-            case GridPortableMarshaller.FLOAT:
-            case GridPortableMarshaller.INT:
-                len = 4;
-
-                break;
-
-            case GridPortableMarshaller.ENUM:
-                //skipping type id and ordinal value
-                len = 8;
-
-                break;
-
-            case GridPortableMarshaller.LONG:
-            case GridPortableMarshaller.DOUBLE:
-                len = 8;
-
-                break;
-
-            case GridPortableMarshaller.BYTE_ARR:
-            case GridPortableMarshaller.BOOLEAN_ARR:
-                len = 4 + readLength();
-
-                break;
-
-            case GridPortableMarshaller.STRING:
-                len = 4 + readStringLength();
-
-                break;
-
-            case GridPortableMarshaller.DECIMAL:
-                len = /** scale */ 4  + /** mag len */ 4  + /** mag bytes count */ readInt(4);
-
-                break;
-
-            case GridPortableMarshaller.UUID:
-                len = 8 + 8;
-
-                break;
-
-            case GridPortableMarshaller.DATE:
-                len = 8 + 4;
-
-                break;
-
-            case GridPortableMarshaller.CHAR_ARR:
-            case GridPortableMarshaller.SHORT_ARR:
-                len = 4 + readLength() * 2;
-
-                break;
-
-            case GridPortableMarshaller.INT_ARR:
-            case GridPortableMarshaller.FLOAT_ARR:
-                len = 4 + readLength() * 4;
-
-                break;
-
-            case GridPortableMarshaller.LONG_ARR:
-            case GridPortableMarshaller.DOUBLE_ARR:
-                len = 4 + readLength() * 8;
-
-                break;
-
-            case GridPortableMarshaller.DECIMAL_ARR:
-            case GridPortableMarshaller.DATE_ARR:
-            case GridPortableMarshaller.OBJ_ARR:
-            case GridPortableMarshaller.ENUM_ARR:
-            case GridPortableMarshaller.UUID_ARR:
-            case GridPortableMarshaller.STRING_ARR: {
-                int size = readInt();
-
-                for (int i = 0; i < size; i++)
-                    skipValue();
-
-                return;
-            }
-
-            case GridPortableMarshaller.COL: {
-                int size = readInt();
-
-                pos++; // skip collection type
-
-                for (int i = 0; i < size; i++)
-                    skipValue();
-
-                return;
-            }
-
-            case GridPortableMarshaller.MAP: {
-                int size = readInt();
-
-                pos++; // skip collection type
-
-                for (int i = 0; i < size; i++) {
-                    skipValue(); // skip key.
-                    skipValue(); // skip value.
-                }
-
-                return;
-            }
-
-            case GridPortableMarshaller.MAP_ENTRY:
-                skipValue();
-                skipValue();
-
-                return;
-
-            case GridPortableMarshaller.PORTABLE_OBJ:
-                len = readInt() + 4;
-
-                break;
-
-            default:
-                throw new PortableException("Invalid flag value: " + type);
-        }
-
-        pos += len;
-    }
-
-    /**
-     * @param pos Position.
-     * @param len Length.
-     * @return Object.
-     */
-    public Object getValueQuickly(int pos, int len) {
-        byte type = arr[pos];
-
-        switch (type) {
-            case GridPortableMarshaller.NULL:
-                return null;
-
-            case GridPortableMarshaller.HANDLE: {
-                int objStart = pos - readIntAbsolute(pos + 1);
-
-                PortableBuilderImpl res = objMap.get(objStart);
-
-                if (res == null) {
-                    res = new PortableBuilderImpl(this, objStart);
-
-                    objMap.put(objStart, res);
-                }
-
-                return res;
-            }
-
-            case GridPortableMarshaller.OBJ: {
-                PortableBuilderImpl res = objMap.get(pos);
-
-                if (res == null) {
-                    res = new PortableBuilderImpl(this, pos);
-
-                    objMap.put(pos, res);
-                }
-
-                return res;
-            }
-
-            case GridPortableMarshaller.BYTE:
-                return arr[pos + 1];
-
-            case GridPortableMarshaller.SHORT:
-                return PRIM.readShort(arr, pos + 1);
-
-            case GridPortableMarshaller.INT:
-                return PRIM.readInt(arr, pos + 1);
-
-            case GridPortableMarshaller.LONG:
-                return PRIM.readLong(arr, pos + 1);
-
-            case GridPortableMarshaller.FLOAT:
-                return PRIM.readFloat(arr, pos + 1);
-
-            case GridPortableMarshaller.DOUBLE:
-                return PRIM.readDouble(arr, pos + 1);
-
-            case GridPortableMarshaller.CHAR:
-                return PRIM.readChar(arr, pos + 1);
-
-            case GridPortableMarshaller.BOOLEAN:
-                return arr[pos + 1] != 0;
-
-            case GridPortableMarshaller.DECIMAL:
-            case GridPortableMarshaller.STRING:
-            case GridPortableMarshaller.UUID:
-            case GridPortableMarshaller.DATE:
-            case GridPortableMarshaller.BYTE_ARR:
-            case GridPortableMarshaller.SHORT_ARR:
-            case GridPortableMarshaller.INT_ARR:
-            case GridPortableMarshaller.LONG_ARR:
-            case GridPortableMarshaller.FLOAT_ARR:
-            case GridPortableMarshaller.DOUBLE_ARR:
-            case GridPortableMarshaller.CHAR_ARR:
-            case GridPortableMarshaller.BOOLEAN_ARR:
-            case GridPortableMarshaller.DECIMAL_ARR:
-            case GridPortableMarshaller.DATE_ARR:
-            case GridPortableMarshaller.UUID_ARR:
-            case GridPortableMarshaller.STRING_ARR:
-                return new PortablePlainLazyValue(this, pos, len);
-
-            case GridPortableMarshaller.COL:
-            case GridPortableMarshaller.OBJ_ARR:
-            case GridPortableMarshaller.MAP:
-            case GridPortableMarshaller.ENUM_ARR:
-            case GridPortableMarshaller.MAP_ENTRY:
-                return new LazyCollection(pos);
-
-            case GridPortableMarshaller.ENUM: {
-                if (len == 1) {
-                    assert readByte(pos) == GridPortableMarshaller.NULL;
-
-                    return null;
-                }
-
-                int mark = position();
-                position(pos + 1);
-
-                PortableBuilderEnum builderEnum = new PortableBuilderEnum(this);
-
-                position(mark);
-
-                return builderEnum;
-            }
-
-            case GridPortableMarshaller.PORTABLE_OBJ: {
-                int size = readIntAbsolute(pos + 1);
-
-                int start = readIntAbsolute(pos + 4 + size);
-
-                PortableObjectImpl portableObj = new PortableObjectImpl(ctx, arr, pos + 4 + start);
-
-                return new PortablePlainPortableObject(portableObj);
-            }
-
-            default:
-                throw new PortableException("Invalid flag value: " + type);
-        }
-    }
-
-    /**
-     * @return Parsed value.
-     */
-    public Object parseValue() {
-        int valPos = pos;
-
-        byte type = arr[pos++];
-
-        int plainLazyValLen;
-
-        switch (type) {
-            case GridPortableMarshaller.NULL:
-                return null;
-
-            case GridPortableMarshaller.HANDLE: {
-                int objStart = pos - 1 - readInt();
-
-                PortableBuilderImpl res = objMap.get(objStart);
-
-                if (res == null) {
-                    res = new PortableBuilderImpl(this, objStart);
-
-                    objMap.put(objStart, res);
-                }
-
-                return res;
-            }
-
-            case GridPortableMarshaller.OBJ: {
-                pos--;
-
-                PortableBuilderImpl res = objMap.get(pos);
-
-                if (res == null) {
-                    res = new PortableBuilderImpl(this, pos);
-
-                    objMap.put(pos, res);
-                }
-
-                pos += readInt(GridPortableMarshaller.TOTAL_LEN_POS);
-
-                return res;
-            }
-
-            case GridPortableMarshaller.BYTE:
-                return arr[pos++];
-
-            case GridPortableMarshaller.SHORT: {
-                Object res = PRIM.readShort(arr, pos);
-                pos += 2;
-                return res;
-            }
-
-            case GridPortableMarshaller.INT:
-                return readInt();
-
-            case GridPortableMarshaller.LONG:
-                plainLazyValLen = 8;
-
-                break;
-
-            case GridPortableMarshaller.FLOAT:
-                plainLazyValLen = 4;
-
-                break;
-
-            case GridPortableMarshaller.DOUBLE:
-                plainLazyValLen = 8;
-
-                break;
-
-            case GridPortableMarshaller.CHAR:
-                plainLazyValLen = 2;
-
-                break;
-
-            case GridPortableMarshaller.BOOLEAN:
-                return arr[pos++] != 0;
-
-            case GridPortableMarshaller.DECIMAL:
-                plainLazyValLen = /** scale */ 4  + /** mag len */ 4  + /** mag bytes count */ readInt(4);
-
-                break;
-
-            case GridPortableMarshaller.STRING:
-                plainLazyValLen = 4 + readStringLength();
-
-                break;
-
-            case GridPortableMarshaller.UUID:
-                plainLazyValLen = 8 + 8;
-
-                break;
-
-            case GridPortableMarshaller.DATE:
-                plainLazyValLen = 8 + 4;
-
-                break;
-
-            case GridPortableMarshaller.BYTE_ARR:
-                plainLazyValLen = 4 + readLength();
-
-                break;
-
-            case GridPortableMarshaller.SHORT_ARR:
-                plainLazyValLen = 4 + readLength() * 2;
-
-                break;
-
-            case GridPortableMarshaller.INT_ARR:
-                plainLazyValLen = 4 + readLength() * 4;
-
-                break;
-
-            case GridPortableMarshaller.LONG_ARR:
-                plainLazyValLen = 4 + readLength() * 8;
-
-                break;
-
-            case GridPortableMarshaller.FLOAT_ARR:
-                plainLazyValLen = 4 + readLength() * 4;
-
-                break;
-
-            case GridPortableMarshaller.DOUBLE_ARR:
-                plainLazyValLen = 4 + readLength() * 8;
-
-                break;
-
-            case GridPortableMarshaller.CHAR_ARR:
-                plainLazyValLen = 4 + readLength() * 2;
-
-                break;
-
-            case GridPortableMarshaller.BOOLEAN_ARR:
-                plainLazyValLen = 4 + readLength();
-
-                break;
-
-            case GridPortableMarshaller.OBJ_ARR:
-                return new PortableObjectArrayLazyValue(this);
-
-            case GridPortableMarshaller.DATE_ARR: {
-                int size = readInt();
-
-                Date[] res = new Date[size];
-
-                for (int i = 0; i < res.length; i++) {
-                    byte flag = arr[pos++];
-
-                    if (flag == GridPortableMarshaller.NULL) continue;
-
-                    if (flag != GridPortableMarshaller.DATE)
-                        throw new PortableException("Invalid flag value: " + flag);
-
-                    long time = PRIM.readLong(arr, pos);
-
-                    pos += 8;
-
-                    if (ctx.isUseTimestamp()) {
-                        Timestamp ts = new Timestamp(time);
-
-                        ts.setNanos(ts.getNanos() + readInt());
-
-                        res[i] = ts;
-                    }
-                    else {
-                        res[i] = new Date(time);
-
-                        pos += 4;
-                    }
-                }
-
-                return res;
-            }
-
-            case GridPortableMarshaller.UUID_ARR:
-            case GridPortableMarshaller.STRING_ARR:
-            case GridPortableMarshaller.DECIMAL_ARR: {
-                int size = readInt();
-
-                for (int i = 0; i < size; i++) {
-                    byte flag = arr[pos++];
-
-                    if (flag == GridPortableMarshaller.UUID)
-                        pos += 8 + 8;
-                    else if (flag == GridPortableMarshaller.STRING)
-                        pos += 4 + readStringLength();
-                    else if (flag == GridPortableMarshaller.DECIMAL)
-                        pos += 4 + readLength();
-                    else
-                        assert flag == GridPortableMarshaller.NULL;
-                }
-
-                return new PortablePlainLazyValue(this, valPos, pos - valPos);
-            }
-
-            case GridPortableMarshaller.COL: {
-                int size = readInt();
-                byte colType = arr[pos++];
-
-                switch (colType) {
-                    case GridPortableMarshaller.USER_COL:
-                    case GridPortableMarshaller.ARR_LIST:
-                        return new PortableLazyArrayList(this, size);
-
-                    case GridPortableMarshaller.LINKED_LIST:
-                        return new PortableLazyLinkedList(this, size);
-
-                    case GridPortableMarshaller.HASH_SET:
-                    case GridPortableMarshaller.LINKED_HASH_SET:
-                    case GridPortableMarshaller.TREE_SET:
-                    case GridPortableMarshaller.CONC_SKIP_LIST_SET:
-                        return new PortableLazySet(this, size);
-                }
-
-                throw new PortableException("Unknown collection type: " + colType);
-            }
-
-            case GridPortableMarshaller.MAP:
-                return PortableLazyMap.parseMap(this);
-
-            case GridPortableMarshaller.ENUM:
-                return new PortableBuilderEnum(this);
-
-            case GridPortableMarshaller.ENUM_ARR:
-                return new PortableEnumArrayLazyValue(this);
-
-            case GridPortableMarshaller.MAP_ENTRY:
-                return new PortableLazyMapEntry(this);
-
-            case GridPortableMarshaller.PORTABLE_OBJ: {
-                int size = readInt();
-
-                pos += size;
-
-                int start = readInt();
-
-                PortableObjectImpl portableObj = new PortableObjectImpl(ctx, arr,
-                    pos - 4 - size + start);
-
-                return new PortablePlainPortableObject(portableObj);
-            }
-
-
-            default:
-                throw new PortableException("Invalid flag value: " + type);
-        }
-
-        PortablePlainLazyValue res = new PortablePlainLazyValue(this, valPos, 1 + plainLazyValLen);
-
-        pos += plainLazyValLen;
-
-        return res;
-    }
-
-    /**
-     * @return Array.
-     */
-    public byte[] array() {
-        return arr;
-    }
-
-    /**
-     * @return Position of reader.
-     */
-    public int position() {
-        return pos;
-    }
-
-    /**
-     * @param pos New pos.
-     */
-    public void position(int pos) {
-        this.pos = pos;
-    }
-
-    /**
-     * @param n Number of bytes to skip.
-     */
-    public void skip(int n) {
-        pos += n;
-    }
-
-    /**
-     * @return Reader.
-     */
-    PortableReaderExImpl reader() {
-        return reader;
-    }
-
-    /**
-     *
-     */
-    private class LazyCollection implements PortableLazyValue {
-        /** */
-        private final int valOff;
-
-        /** */
-        private Object col;
-
-        /**
-         * @param valOff Value.
-         */
-        protected LazyCollection(int valOff) {
-            this.valOff = valOff;
-        }
-
-        /**
-         * @return Object.
-         */
-        private Object wrappedCollection() {
-            if (col == null) {
-                position(valOff);
-
-                col = parseValue();
-            }
-
-            return col;
-        }
-
-        /** {@inheritDoc} */
-        @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
-            ctx.writeValue(writer, wrappedCollection());
-        }
-
-        /** {@inheritDoc} */
-        @Override public Object value() {
-            return PortableUtils.unwrapLazy(wrappedCollection());
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderSerializationAware.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderSerializationAware.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderSerializationAware.java
deleted file mode 100644
index d75cd7b..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderSerializationAware.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-/**
- *
- */
-interface PortableBuilderSerializationAware {
-    /**
-     * @param writer Writer.
-     * @param ctx Context.
-     */
-    public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx);
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderSerializer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderSerializer.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderSerializer.java
deleted file mode 100644
index 6ce9f4c..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderSerializer.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-import java.util.Collection;
-import java.util.IdentityHashMap;
-import java.util.Map;
-import org.apache.ignite.internal.util.GridConcurrentSkipListSet;
-import org.apache.ignite.portable.PortableObject;
-
-/**
- *
- */
-class PortableBuilderSerializer {
-    /** */
-    private final Map<PortableBuilderImpl, Integer> objToPos = new IdentityHashMap<>();
-
-    /** */
-    private Map<PortableObject, PortableBuilderImpl> portableObjToWrapper;
-
-    /**
-     * @param obj Mutable object.
-     * @param posInResArr Object position in the array.
-     */
-    public void registerObjectWriting(PortableBuilderImpl obj, int posInResArr) {
-        objToPos.put(obj, posInResArr);
-    }
-
-    /**
-     * @param writer Writer.
-     * @param val Value.
-     */
-    public void writeValue(PortableWriterExImpl writer, Object val) {
-        if (val == null) {
-            writer.writeByte(GridPortableMarshaller.NULL);
-
-            return;
-        }
-
-        if (val instanceof PortableBuilderSerializationAware) {
-            ((PortableBuilderSerializationAware)val).writeTo(writer, this);
-
-            return;
-        }
-
-        if (val instanceof PortableObjectEx) {
-            if (portableObjToWrapper == null)
-                portableObjToWrapper = new IdentityHashMap<>();
-
-            PortableBuilderImpl wrapper = portableObjToWrapper.get(val);
-
-            if (wrapper == null) {
-                wrapper = PortableBuilderImpl.wrap((PortableObject)val);
-
-                portableObjToWrapper.put((PortableObject)val, wrapper);
-            }
-
-            val = wrapper;
-        }
-
-        if (val instanceof PortableBuilderImpl) {
-            PortableBuilderImpl obj = (PortableBuilderImpl)val;
-
-            Integer posInResArr = objToPos.get(obj);
-
-            if (posInResArr == null) {
-                objToPos.put(obj, writer.outputStream().position());
-
-                obj.serializeTo(writer.newWriter(obj.typeId()), this);
-            }
-            else {
-                int handle = writer.outputStream().position() - posInResArr;
-
-                writer.writeByte(GridPortableMarshaller.HANDLE);
-                writer.writeInt(handle);
-            }
-
-            return;
-        }
-
-        if (val.getClass().isEnum()) {
-            writer.writeByte(GridPortableMarshaller.ENUM);
-            writer.writeInt(writer.context().typeId(val.getClass().getName()));
-            writer.writeInt(((Enum)val).ordinal());
-
-            return;
-        }
-
-        if (val instanceof Collection) {
-            Collection<?> c = (Collection<?>)val;
-
-            writer.writeByte(GridPortableMarshaller.COL);
-            writer.writeInt(c.size());
-
-            byte colType;
-
-            if (c instanceof GridConcurrentSkipListSet)
-                colType = GridPortableMarshaller.CONC_SKIP_LIST_SET;
-            else
-                colType = writer.context().collectionType(c.getClass());
-
-
-            writer.writeByte(colType);
-
-            for (Object obj : c)
-                writeValue(writer, obj);
-
-            return;
-        }
-
-        if (val instanceof Map) {
-            Map<?, ?> map = (Map<?, ?>)val;
-
-            writer.writeByte(GridPortableMarshaller.MAP);
-            writer.writeInt(map.size());
-
-            writer.writeByte(writer.context().mapType(map.getClass()));
-
-            for (Map.Entry<?, ?> entry : map.entrySet()) {
-                writeValue(writer, entry.getKey());
-                writeValue(writer, entry.getValue());
-            }
-
-            return;
-        }
-
-        Byte flag = PortableUtils.PLAIN_CLASS_TO_FLAG.get(val.getClass());
-
-        if (flag != null) {
-            PortableUtils.writePlainObject(writer, val);
-
-            return;
-        }
-
-        if (val instanceof Object[]) {
-            int compTypeId = writer.context().typeId(((Object[])val).getClass().getComponentType().getName());
-
-            if (val instanceof PortableBuilderEnum[]) {
-                writeArray(writer, GridPortableMarshaller.ENUM_ARR, (Object[])val, compTypeId);
-
-                return;
-            }
-
-            if (((Object[])val).getClass().getComponentType().isEnum()) {
-                Enum[] enumArr = (Enum[])val;
-
-                writer.writeByte(GridPortableMarshaller.ENUM_ARR);
-                writer.writeInt(compTypeId);
-                writer.writeInt(enumArr.length);
-
-                for (Enum anEnum : enumArr)
-                    writeValue(writer, anEnum);
-
-                return;
-            }
-
-            writeArray(writer, GridPortableMarshaller.OBJ_ARR, (Object[])val, compTypeId);
-
-            return;
-        }
-
-        writer.doWriteObject(val, false);
-    }
-
-    /**
-     * @param writer Writer.
-     * @param elementType Element type.
-     * @param arr The array.
-     * @param compTypeId Component type ID.
-     */
-    public void writeArray(PortableWriterExImpl writer, byte elementType, Object[] arr, int compTypeId) {
-        writer.writeByte(elementType);
-        writer.writeInt(compTypeId);
-        writer.writeInt(arr.length);
-
-        for (Object obj : arr)
-            writeValue(writer, obj);
-    }
-
-    /**
-     * @param writer Writer.
-     * @param elementType Element type.
-     * @param arr The array.
-     * @param clsName Component class name.
-     */
-    public void writeArray(PortableWriterExImpl writer, byte elementType, Object[] arr, String clsName) {
-        writer.writeByte(elementType);
-        writer.writeInt(GridPortableMarshaller.UNREGISTERED_TYPE_ID);
-        writer.writeString(clsName);
-        writer.writeInt(arr.length);
-
-        for (Object obj : arr)
-            writeValue(writer, obj);
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java
index 7e4266c..24ad5ce 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java
@@ -48,7 +48,7 @@ import static java.lang.reflect.Modifier.isTransient;
 /**
  * Portable class descriptor.
  */
-class PortableClassDescriptor {
+public class PortableClassDescriptor {
     /** */
     private final PortableContext ctx;
 
@@ -123,7 +123,7 @@ class PortableClassDescriptor {
         boolean keepDeserialized
     ) throws PortableException {
         this(ctx, cls, userType, typeId, typeName, idMapper, serializer, useTs, metaDataEnabled, keepDeserialized,
-             true);
+            true);
     }
 
     /**
@@ -285,7 +285,7 @@ class PortableClassDescriptor {
     /**
      * @return Type ID.
      */
-    int typeId() {
+    public int typeId() {
         return typeId;
     }
 
@@ -399,7 +399,7 @@ class PortableClassDescriptor {
                 break;
 
             case DECIMAL:
-                writer.doWriteDecimal((BigDecimal) obj);
+                writer.doWriteDecimal((BigDecimal)obj);
 
                 break;
 
@@ -656,39 +656,32 @@ class PortableClassDescriptor {
      * @return Whether further write is needed.
      */
     private boolean writeHeader(Object obj, PortableWriterExImpl writer) {
-        int handle = writer.handle(obj);
-
-        if (handle >= 0) {
-            writer.doWriteByte(GridPortableMarshaller.HANDLE);
-            writer.doWriteInt(handle);
-
+        if (writer.tryWriteAsHandle(obj))
             return false;
-        }
-        else {
-            int pos = writer.position();
 
-            writer.doWriteByte(GridPortableMarshaller.OBJ);
-            writer.doWriteBoolean(userType);
-            writer.doWriteInt(registered ? typeId : GridPortableMarshaller.UNREGISTERED_TYPE_ID);
-            writer.doWriteInt(obj instanceof CacheObjectImpl ? 0 : obj.hashCode());
+        int pos = writer.position();
 
-            // For length and raw offset.
-            int reserved = writer.reserve(8);
+        writer.doWriteByte(GridPortableMarshaller.OBJ);
+        writer.doWriteBoolean(userType);
+        writer.doWriteInt(registered ? typeId : GridPortableMarshaller.UNREGISTERED_TYPE_ID);
+        writer.doWriteInt(obj instanceof CacheObjectImpl ? 0 : obj.hashCode());
 
-            // Class name in case if typeId registration is failed.
-            if (!registered)
-                writer.doWriteString(cls.getName());
+        // For length and raw offset.
+        int reserved = writer.reserve(8);
 
-            int current = writer.position();
-            int len = current - pos;
+        // Class name in case if typeId registration is failed.
+        if (!registered)
+            writer.doWriteString(cls.getName());
 
-            // Default raw offset (equal to header length).
-            writer.position(reserved + 4);
-            writer.doWriteInt(len);
-            writer.position(current);
+        int current = writer.position();
+        int len = current - pos;
 
-            return true;
-        }
+        // Default raw offset (equal to header length).
+        writer.position(reserved + 4);
+        writer.doWriteInt(len);
+        writer.position(current);
+
+        return true;
     }
 
     /**
@@ -787,7 +780,7 @@ class PortableClassDescriptor {
         else if (cls == PortableObjectImpl.class)
             return Mode.PORTABLE_OBJ;
         else if (PortableMarshalAware.class.isAssignableFrom(cls))
-           return Mode.PORTABLE;
+            return Mode.PORTABLE;
         else if (Externalizable.class.isAssignableFrom(cls))
             return Mode.EXTERNALIZABLE;
         else if (Map.Entry.class.isAssignableFrom(cls))
@@ -1352,4 +1345,4 @@ class PortableClassDescriptor {
             return typeName;
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableContext.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableContext.java
index 15b6433..db7e41e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableContext.java
@@ -794,10 +794,10 @@ public class PortableContext implements Externalizable {
      * @param typeId Type ID.
      * @return Whether meta data is enabled.
      */
-    boolean isMetaDataEnabled(int typeId) {
+    public boolean isMetaDataEnabled(int typeId) {
         Boolean enabled = metaEnabled.get(typeId);
 
-        return enabled != null ? enabled : true;
+        return enabled != null ? enabled : metaDataEnabled;
     }
 
     /**
@@ -827,7 +827,7 @@ public class PortableContext implements Externalizable {
      * @param fields Fields map.
      * @throws PortableException In case of error.
      */
-    void updateMetaData(int typeId, String typeName, Map<String, String> fields) throws PortableException {
+    public void updateMetaData(int typeId, String typeName, Map<String, String> fields) throws PortableException {
         updateMetaData(typeId, new PortableMetaDataImpl(typeName, fields, null));
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableEnumArrayLazyValue.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableEnumArrayLazyValue.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableEnumArrayLazyValue.java
deleted file mode 100644
index c953bb3..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableEnumArrayLazyValue.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.portable.PortableException;
-import org.apache.ignite.portable.PortableInvalidClassException;
-
-/**
- *
- */
-class PortableEnumArrayLazyValue extends PortableAbstractLazyValue {
-    /** */
-    private final int len;
-
-    /** */
-    private final int compTypeId;
-
-    /** */
-    private final String clsName;
-
-    /**
-     * @param reader Reader.
-     */
-    protected PortableEnumArrayLazyValue(PortableBuilderReader reader) {
-        super(reader, reader.position() - 1);
-
-        int typeId = reader.readInt();
-
-        if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) {
-            clsName = reader.readString();
-
-            Class cls;
-
-            try {
-                // TODO: IGNITE-1272 - Is class loader needed here?
-                cls = U.forName(reader.readString(), null);
-            }
-            catch (ClassNotFoundException e) {
-                throw new PortableInvalidClassException("Failed to load the class: " + clsName, e);
-            }
-
-            compTypeId = reader.portableContext().descriptorForClass(cls).typeId();
-        }
-        else {
-            compTypeId = typeId;
-            clsName = null;
-        }
-
-        int size = reader.readInt();
-
-        for (int i = 0; i < size; i++)
-            reader.skipValue();
-
-        len = reader.position() - valOff;
-    }
-
-    /** {@inheritDoc} */
-    @Override protected Object init() {
-        reader.position(valOff + 1);
-
-        //skipping component type id
-        reader.readInt();
-
-        int size = reader.readInt();
-
-        PortableBuilderEnum[] res = new PortableBuilderEnum[size];
-
-        for (int i = 0; i < size; i++) {
-            byte flag = reader.readByte();
-
-            if (flag == GridPortableMarshaller.NULL)
-                continue;
-
-            if (flag != GridPortableMarshaller.ENUM)
-                throw new PortableException("Invalid flag value: " + flag);
-
-            res[i] = new PortableBuilderEnum(reader);
-        }
-
-        return res;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
-        if (val != null) {
-            if (clsName != null)
-                ctx.writeArray(writer, GridPortableMarshaller.ENUM_ARR, (Object[])val, clsName);
-            else
-                ctx.writeArray(writer, GridPortableMarshaller.ENUM_ARR, (Object[])val, compTypeId);
-
-            return;
-        }
-
-        writer.write(reader.array(), valOff, len);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyArrayList.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyArrayList.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyArrayList.java
deleted file mode 100644
index 84a0c22..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyArrayList.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-import java.util.AbstractList;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- *
- */
-class PortableLazyArrayList extends AbstractList<Object> implements PortableBuilderSerializationAware {
-    /** */
-    private final PortableBuilderReader reader;
-
-    /** */
-    private final int off;
-
-    /** */
-    private List<Object> delegate;
-
-    /**
-     * @param reader Reader.
-     * @param size Size,
-     */
-    PortableLazyArrayList(PortableBuilderReader reader, int size) {
-        this.reader = reader;
-        off = reader.position() - 1/* flag */ - 4/* size */ - 1/* col type */;
-
-        assert size >= 0;
-
-        for (int i = 0; i < size; i++)
-            reader.skipValue();
-    }
-
-    /**
-     *
-     */
-    private void ensureDelegateInit() {
-        if (delegate == null) {
-            int size = reader.readIntAbsolute(off + 1);
-
-            reader.position(off + 1/* flag */ + 4/* size */ + 1/* col type */);
-
-            delegate = new ArrayList<>(size);
-
-            for (int i = 0; i < size; i++)
-                delegate.add(reader.parseValue());
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object get(int idx) {
-        ensureDelegateInit();
-
-        return PortableUtils.unwrapLazy(delegate.get(idx));
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean add(Object o) {
-        ensureDelegateInit();
-
-        return delegate.add(o);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void add(int idx, Object element) {
-        ensureDelegateInit();
-
-        delegate.add(idx, element);
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object set(int idx, Object element) {
-        ensureDelegateInit();
-
-        return PortableUtils.unwrapLazy(delegate.set(idx, element));
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object remove(int idx) {
-        ensureDelegateInit();
-
-        return PortableUtils.unwrapLazy(delegate.remove(idx));
-    }
-
-    /** {@inheritDoc} */
-    @Override public void clear() {
-        if (delegate == null)
-            delegate = new ArrayList<>();
-        else
-            delegate.clear();
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean addAll(int idx, Collection<?> c) {
-        return delegate.addAll(idx, c);
-    }
-
-    /** {@inheritDoc} */
-    @Override protected void removeRange(int fromIdx, int toIdx) {
-        ensureDelegateInit();
-
-        delegate.subList(fromIdx, toIdx).clear();
-    }
-
-    /** {@inheritDoc} */
-    @Override public int size() {
-        if (delegate == null)
-            return reader.readIntAbsolute(off + 1);
-
-        return delegate.size();
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
-        if (delegate == null) {
-            int size = reader.readIntAbsolute(off + 1);
-
-            int hdrSize = 1 /* flag */ + 4 /* size */ + 1 /* col type */;
-
-            writer.write(reader.array(), off, hdrSize);
-
-            reader.position(off + hdrSize);
-
-            for (int i = 0; i < size; i++) {
-                Object o = reader.parseValue();
-
-                ctx.writeValue(writer, o);
-            }
-        }
-        else {
-            writer.writeByte(GridPortableMarshaller.COL);
-            writer.writeInt(delegate.size());
-
-            byte colType = reader.array()[off + 1 /* flag */ + 4 /* size */];
-            writer.writeByte(colType);
-
-            for (Object o : delegate)
-                ctx.writeValue(writer, o);
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/6ac9557e/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyLinkedList.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyLinkedList.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyLinkedList.java
deleted file mode 100644
index 7b2e15a..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableLazyLinkedList.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * 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.ignite.internal.portable;
-
-import java.util.AbstractList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-
-/**
- *
- */
-class PortableLazyLinkedList extends AbstractList<Object> implements PortableBuilderSerializationAware {
-    /** */
-    private final PortableBuilderReader reader;
-
-    /** */
-    private final int off;
-
-    /** */
-    private List<Object> delegate;
-
-    /**
-     * @param reader Reader.
-     * @param size Size,
-     */
-    PortableLazyLinkedList(PortableBuilderReader reader, int size) {
-        this.reader = reader;
-        off = reader.position() - 1/* flag */ - 4/* size */ - 1/* col type */;
-
-        assert size >= 0;
-
-        for (int i = 0; i < size; i++)
-            reader.skipValue();
-    }
-
-    /**
-     *
-     */
-    private void ensureDelegateInit() {
-        if (delegate == null) {
-            int size = reader.readIntAbsolute(off + 1);
-
-            reader.position(off + 1/* flag */ + 4/* size */ + 1/* col type */);
-
-            delegate = new LinkedList<>();
-
-            for (int i = 0; i < size; i++)
-                delegate.add(reader.parseValue());
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object get(int idx) {
-        ensureDelegateInit();
-
-        return PortableUtils.unwrapLazy(delegate.get(idx));
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean add(Object o) {
-        ensureDelegateInit();
-
-        return delegate.add(o);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void add(int idx, Object element) {
-        ensureDelegateInit();
-
-        delegate.add(idx, element);
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object set(int idx, Object element) {
-        ensureDelegateInit();
-
-        return PortableUtils.unwrapLazy(delegate.set(idx, element));
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object remove(int idx) {
-        ensureDelegateInit();
-
-        return PortableUtils.unwrapLazy(delegate.remove(idx));
-    }
-
-    /** {@inheritDoc} */
-    @Override public void clear() {
-        if (delegate == null)
-            delegate = new LinkedList<>();
-        else
-            delegate.clear();
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean addAll(int idx, Collection<?> c) {
-        ensureDelegateInit();
-
-        return delegate.addAll(idx, c);
-    }
-
-    /** {@inheritDoc} */
-    @Override protected void removeRange(int fromIdx, int toIdx) {
-        ensureDelegateInit();
-
-        delegate.subList(fromIdx, toIdx).clear();
-    }
-
-    /** {@inheritDoc} */
-    @Override public int size() {
-        if (delegate == null)
-            return reader.readIntAbsolute(off + 1);
-
-        return delegate.size();
-    }
-
-    /** {@inheritDoc} */
-    @Override public ListIterator<Object> listIterator(final int idx) {
-        ensureDelegateInit();
-
-        return new ListIterator<Object>() {
-            /** */
-            private final ListIterator<Object> delegate = PortableLazyLinkedList.super.listIterator(idx);
-
-            @Override public boolean hasNext() {
-                return delegate.hasNext();
-            }
-
-            @Override public Object next() {
-                return PortableUtils.unwrapLazy(delegate.next());
-            }
-
-            @Override public boolean hasPrevious() {
-                return delegate.hasPrevious();
-            }
-
-            @Override public Object previous() {
-                return PortableUtils.unwrapLazy(delegate.previous());
-            }
-
-            @Override public int nextIndex() {
-                return delegate.nextIndex();
-            }
-
-            @Override public int previousIndex() {
-                return delegate.previousIndex();
-            }
-
-            @Override public void remove() {
-                delegate.remove();
-            }
-
-            @Override public void set(Object o) {
-                delegate.set(o);
-            }
-
-            @Override public void add(Object o) {
-                delegate.add(o);
-            }
-        };
-    }
-
-    /** {@inheritDoc} */
-    @Override public Iterator<Object> iterator() {
-        ensureDelegateInit();
-
-        return PortableUtils.unwrapLazyIterator(super.iterator());
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) {
-        if (delegate == null) {
-            int size = reader.readIntAbsolute(off + 1);
-
-            int hdrSize = 1 /* flag */ + 4 /* size */ + 1 /* col type */;
-            writer.write(reader.array(), off, hdrSize);
-
-            reader.position(off + hdrSize);
-
-            for (int i = 0; i < size; i++) {
-                Object o = reader.parseValue();
-
-                ctx.writeValue(writer, o);
-            }
-        }
-        else {
-            writer.writeByte(GridPortableMarshaller.COL);
-            writer.writeInt(delegate.size());
-
-            byte colType = reader.array()[off + 1 /* flag */ + 4 /* size */];
-            writer.writeByte(colType);
-
-            for (Object o : delegate)
-                ctx.writeValue(writer, o);
-        }
-    }
-}
\ No newline at end of file