http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/4662feca/modules/core/src/main/java/org/apache/ignite/internal/portable/GridPortableWriterExImpl.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/portable/GridPortableWriterExImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/portable/GridPortableWriterExImpl.java
deleted file mode 100644
index f5df6d6..0000000
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/portable/GridPortableWriterExImpl.java
+++ /dev/null
@@ -1,1770 +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.*;
-import org.apache.ignite.internal.portable.streams.*;
-import org.apache.ignite.internal.processors.portable.*;
-import org.apache.ignite.internal.util.typedef.internal.*;
-import org.apache.ignite.portable.*;
-
-import org.jetbrains.annotations.*;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.math.*;
-import java.sql.*;
-import java.util.*;
-import java.util.Date;
-import java.util.concurrent.*;
-
-import static java.nio.charset.StandardCharsets.*;
-import static org.apache.ignite.internal.portable.GridPortableMarshaller.*;
-
- /**
- * Portable writer implementation.
- */
-public class GridPortableWriterExImpl implements PortableWriter, 
GridPortableRawWriterEx, ObjectOutput {
-    /** Length: integer. */
-    private static final int LEN_INT = 4;
-
-    /** */
-    private static final int INIT_CAP = 1024;
-
-    /** */
-    private static final ConcurrentHashMap<Class<?>, Boolean> useOptMarshCache 
= new ConcurrentHashMap<>();
-
-    /** */
-    private final GridPortableContext ctx;
-
-    /** */
-    private final WriterContext wCtx;
-
-    /** */
-    private final int start;
-
-    /** */
-    private int mark;
-
-    /** */
-    private Class<?> cls;
-
-    /** */
-    private int typeId;
-
-    /** */
-    private boolean allowFields = true;
-
-    /** */
-    private boolean metaEnabled;
-
-    /** */
-    private int metaHashSum;
-
-    /**
-     * @param ctx Context.
-     * @param off Start offset.
-     */
-    GridPortableWriterExImpl(GridPortableContext ctx, int off) {
-        this.ctx = ctx;
-
-        GridPortableOutputStream out = new GridPortableHeapOutputStream(off + 
INIT_CAP);
-
-        out.position(off);
-
-        wCtx = new WriterContext(out, null);
-
-        start = off;
-    }
-
-    /**
-     * @param ctx Context.
-     * @param out Output stream.
-     * @param off Start offset.
-     */
-    GridPortableWriterExImpl(GridPortableContext ctx, GridPortableOutputStream 
out, int off) {
-        this.ctx = ctx;
-
-        wCtx = new WriterContext(out, null);
-
-        start = off;
-    }
-
-    /**
-     * @param ctx Context.
-     * @param off Start offset.
-     * @param typeId Type ID.
-     */
-    GridPortableWriterExImpl(GridPortableContext ctx, int off, int typeId, 
boolean metaEnabled) {
-        this(ctx, off);
-
-        this.typeId = typeId;
-
-        this.metaEnabled = metaEnabled;
-    }
-
-    /**
-     * @param ctx Context.
-     * @param wCtx Writer context.
-     */
-    private GridPortableWriterExImpl(GridPortableContext ctx, WriterContext 
wCtx) {
-        this.ctx = ctx;
-        this.wCtx = wCtx;
-
-        start = wCtx.out.position();
-    }
-
-    /**
-     * Close the writer releasing resources if necessary.
-     */
-    @Override public void close() {
-        wCtx.out.close();
-    }
-
-    /**
-     * @return Meta data hash sum or {@code null} if meta data is disabled.
-     */
-    @Nullable Integer metaDataHashSum() {
-        return metaEnabled ? metaHashSum : null;
-    }
-
-    /**
-     * @param obj Object.
-     * @param detached Detached or not.
-     * @throws PortableException In case of error.
-     */
-    void marshal(Object obj, boolean detached) throws PortableException {
-        assert obj != null;
-
-        if (useOptimizedMarshaller(obj)) {
-            writeByte(OPTM_MARSH);
-
-            try {
-                byte[] arr = ctx.optimizedMarsh().marshal(obj);
-
-                writeInt(arr.length);
-
-                write(arr);
-            }
-            catch (IgniteCheckedException e) {
-                throw new PortableException("Failed to marshal object with 
optimized marshaller: " + obj, e);
-            }
-
-            return;
-        }
-
-        cls = obj.getClass();
-
-        GridPortableClassDescriptor desc = ctx.descriptorForClass(cls);
-
-        if (desc == null)
-            throw new PortableException("Object is not portable: [class=" + 
cls + ']');
-
-        if (desc.excluded()) {
-            doWriteByte(NULL);
-            return;
-        }
-
-        if (desc.getWriteReplaceMethod() != null) {
-            Object replace;
-
-            try {
-                replace = desc.getWriteReplaceMethod().invoke(obj);
-            }
-            catch (IllegalAccessException e) {
-                throw new RuntimeException(e);
-            }
-            catch (InvocationTargetException e) {
-                if (e.getTargetException() instanceof PortableException)
-                    throw (PortableException)e.getTargetException();
-
-                throw new PortableException("Failed to execute writeReplace() 
method on " + obj, e);
-            }
-
-            if (replace == null) {
-                doWriteByte(NULL);
-                return;
-            }
-
-            if (cls != replace.getClass()) {
-                cls = replace.getClass();
-
-                desc = ctx.descriptorForClass(cls);
-
-                if (desc == null)
-                    throw new PortableException("Object is not portable: 
[class=" + cls + ']');
-            }
-
-            obj = replace;
-        }
-
-        typeId = desc.typeId();
-
-        metaEnabled = ctx.isMetaDataEnabled(typeId);
-
-        if (detached)
-            wCtx.resetHandles();
-
-        desc.write(obj, this);
-    }
-
-     /**
-      * Determines whether to use {@link 
org.apache.ignite.marshaller.optimized.OptimizedMarshaller} for serialization
-      * or not.
-      *
-      * @param obj Object to serialize.
-      * @return {@code true} if to use, {@code false} otherwise.
-      */
-     private boolean useOptimizedMarshaller(Object obj) {
-         Class<?> cls = obj.getClass();
-
-         Boolean use = useOptMarshCache.get(cls);
-
-         if (use != null)
-             return use;
-
-         if (ctx.isPredefinedClass(cls))
-             use = false;
-         else {
-             try {
-                 Method writeObj = cls.getDeclaredMethod("writeObject", 
ObjectOutputStream.class);
-                 Method readObj = cls.getDeclaredMethod("readObject", 
ObjectInputStream.class);
-
-                 if (!Modifier.isStatic(writeObj.getModifiers()) && 
!Modifier.isStatic(readObj.getModifiers()) &&
-                     writeObj.getReturnType() == void.class && 
readObj.getReturnType() == void.class)
-                     use = true;
-                 else
-                     use = false;
-
-             } catch (NoSuchMethodException e) {
-                 use = false;
-             }
-         }
-
-         useOptMarshCache.putIfAbsent(cls, use);
-
-         return use;
-     }
-
-    /**
-     * @param obj Object.
-     * @return Handle.
-     */
-    int handle(Object obj) {
-        assert obj != null;
-
-        return wCtx.handle(obj);
-    }
-
-    /**
-     * @return Array.
-     */
-    byte[] array() {
-        return wCtx.out.arrayCopy();
-    }
-
-    /**
-     * @return Output stream.
-     */
-    GridPortableOutputStream outputStream() {
-        return wCtx.out;
-    }
-
-    /**
-     * @return Stream current position.
-     */
-    int position() {
-        return wCtx.out.position();
-    }
-
-    /**
-     * Sets new position.
-     *
-     * @param pos Position.
-     */
-    void position(int pos) {
-        wCtx.out.position(pos);
-    }
-
-     /**
-     * @param bytes Number of bytes to reserve.
-     * @return Offset.
-     */
-    int reserve(int bytes) {
-        int pos = wCtx.out.position();
-
-        wCtx.out.position(pos + bytes);
-
-        return pos;
-    }
-
-    /**
-     * @param bytes Number of bytes to reserve.
-     * @return Offset.
-     */
-    int reserveAndMark(int bytes) {
-        int off0 = reserve(bytes);
-
-        mark = wCtx.out.position();
-
-        return off0;
-    }
-
-    /**
-     * @param off Offset.
-     */
-    void writeDelta(int off) {
-        wCtx.out.writeInt(off, wCtx.out.position() - mark);
-    }
-
-    /**
-     *
-     */
-    void writeLength() {
-        wCtx.out.writeInt(start + TOTAL_LEN_POS, wCtx.out.position() - start);
-    }
-
-    /**
-     *
-     */
-    void writeRawOffsetIfNeeded() {
-        if (allowFields)
-            wCtx.out.writeInt(start + RAW_DATA_OFF_POS, wCtx.out.position() - 
start);
-    }
-
-    /**
-     * @param val Byte array.
-     */
-    public void write(byte[] val) {
-        assert val != null;
-
-        wCtx.out.writeByteArray(val);
-    }
-
-    /**
-     * @param val Byte array.
-     * @param off Offset.
-     * @param len Length.
-     */
-    public void write(byte[] val, int off, int len) {
-        assert val != null;
-
-        wCtx.out.write(val, off, len);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void doWriteByte(byte val) {
-        wCtx.out.writeByte(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void doWriteShort(short val) {
-        wCtx.out.writeShort(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void doWriteInt(int val) {
-        wCtx.out.writeInt(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void doWriteLong(long val) {
-        wCtx.out.writeLong(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void doWriteFloat(float val) {
-        wCtx.out.writeFloat(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void doWriteDouble(double val) {
-        wCtx.out.writeDouble(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void doWriteChar(char val) {
-        wCtx.out.writeChar(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void doWriteBoolean(boolean val) {
-        wCtx.out.writeBoolean(val);
-    }
-
-    /**
-     * @param val String value.
-     */
-    void doWriteDecimal(@Nullable BigDecimal val) {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(DECIMAL);
-
-            BigInteger intVal = val.unscaledValue();
-
-            if (intVal.signum() == -1) {
-                intVal = intVal.negate();
-
-                wCtx.out.writeInt(val.scale() | 0x80000000);
-            }
-            else
-                wCtx.out.writeInt(val.scale());
-
-            byte[] vals = intVal.toByteArray();
-
-            wCtx.out.writeInt(vals.length);
-            wCtx.out.writeByteArray(vals);
-        }
-    }
-
-    /**
-     * @param val String value.
-     */
-    void doWriteString(@Nullable String val) {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(STRING);
-
-            if (ctx.isConvertString()) {
-                doWriteBoolean(true);
-
-                byte[] strArr = val.getBytes(UTF_8);
-
-                doWriteInt(strArr.length);
-
-                wCtx.out.writeByteArray(strArr);
-            }
-            else {
-                doWriteBoolean(false);
-
-                char[] strArr = val.toCharArray();
-
-                doWriteInt(strArr.length);
-
-                wCtx.out.writeCharArray(strArr);
-            }
-        }
-    }
-
-    /**
-     * @param uuid UUID.
-     */
-    void doWriteUuid(@Nullable UUID uuid) {
-        if (uuid == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(UUID);
-            doWriteLong(uuid.getMostSignificantBits());
-            doWriteLong(uuid.getLeastSignificantBits());
-        }
-    }
-
-    /**
-     * @param date Date.
-     */
-    void doWriteDate(@Nullable Date date) {
-        if (date == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(DATE);
-            doWriteLong(date.getTime());
-            doWriteInt(0);
-        }
-    }
-
-    /**
-     * @param ts Timestamp.
-     */
-    void doWriteTimestamp(@Nullable Timestamp ts) {
-        if (ts == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(DATE);
-            doWriteLong(ts.getTime());
-            doWriteInt(ts.getNanos() % 1000000);
-        }
-    }
-
-    /**
-     * @param obj Object.
-     * @param detached Detached or not.
-     * @throws PortableException In case of error.
-     */
-    void doWriteObject(@Nullable Object obj, boolean detached) throws 
PortableException {
-        if (obj == null)
-            doWriteByte(NULL);
-        else {
-            WriterContext wCtx = detached ? new WriterContext(this.wCtx.out, 
this.wCtx.handles) : this.wCtx;
-
-            GridPortableWriterExImpl writer = new 
GridPortableWriterExImpl(ctx, wCtx);
-
-            writer.marshal(obj, detached);
-
-            if (detached)
-                this.wCtx.out = wCtx.out;
-        }
-    }
-
-    /**
-     * @param val Byte array.
-     */
-    void doWriteByteArray(@Nullable byte[] val) {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(BYTE_ARR);
-            doWriteInt(val.length);
-
-            wCtx.out.writeByteArray(val);
-        }
-    }
-
-    /**
-     * @param val Short array.
-     */
-    void doWriteShortArray(@Nullable short[] val) {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(SHORT_ARR);
-            doWriteInt(val.length);
-
-            wCtx.out.writeShortArray(val);
-        }
-    }
-
-    /**
-     * @param val Integer array.
-     */
-    void doWriteIntArray(@Nullable int[] val) {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(INT_ARR);
-            doWriteInt(val.length);
-
-            wCtx.out.writeIntArray(val);
-        }
-    }
-
-    /**
-     * @param val Long array.
-     */
-    void doWriteLongArray(@Nullable long[] val) {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(LONG_ARR);
-            doWriteInt(val.length);
-
-            wCtx.out.writeLongArray(val);
-        }
-    }
-
-    /**
-     * @param val Float array.
-     */
-    void doWriteFloatArray(@Nullable float[] val) {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(FLOAT_ARR);
-            doWriteInt(val.length);
-
-            wCtx.out.writeFloatArray(val);
-        }
-    }
-
-    /**
-     * @param val Double array.
-     */
-    void doWriteDoubleArray(@Nullable double[] val) {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(DOUBLE_ARR);
-            doWriteInt(val.length);
-
-            wCtx.out.writeDoubleArray(val);
-        }
-    }
-
-    /**
-     * @param val Char array.
-     */
-    void doWriteCharArray(@Nullable char[] val) {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(CHAR_ARR);
-            doWriteInt(val.length);
-
-            wCtx.out.writeCharArray(val);
-        }
-    }
-
-    /**
-     * @param val Boolean array.
-     */
-    void doWriteBooleanArray(@Nullable boolean[] val) {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(BOOLEAN_ARR);
-            doWriteInt(val.length);
-
-            wCtx.out.writeBooleanArray(val);
-        }
-    }
-
-    /**
-     * @param val Array of strings.
-     */
-    void doWriteDecimalArray(@Nullable BigDecimal[] val) {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(DECIMAL_ARR);
-            doWriteInt(val.length);
-
-            for (BigDecimal str : val)
-                doWriteDecimal(str);
-        }
-    }
-
-    /**
-     * @param val Array of strings.
-     */
-    void doWriteStringArray(@Nullable String[] val) {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(STRING_ARR);
-            doWriteInt(val.length);
-
-            for (String str : val)
-                doWriteString(str);
-        }
-    }
-
-    /**
-     * @param val Array of UUIDs.
-     */
-    void doWriteUuidArray(@Nullable UUID[] val) {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(UUID_ARR);
-            doWriteInt(val.length);
-
-            for (UUID uuid : val)
-                doWriteUuid(uuid);
-        }
-    }
-
-    /**
-     * @param val Array of dates.
-     */
-    void doWriteDateArray(@Nullable Date[] val) {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(DATE_ARR);
-            doWriteInt(val.length);
-
-            for (Date date : val)
-                doWriteDate(date);
-        }
-    }
-
-    /**
-     * @param val Array of objects.
-     * @throws PortableException In case of error.
-     */
-    void doWriteObjectArray(@Nullable Object[] val) throws PortableException {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            GridPortableContext.Type type = 
ctx.typeId(val.getClass().getComponentType());
-
-            doWriteByte(OBJ_ARR);
-
-            if (type.registered())
-                doWriteInt(type.id());
-            else {
-                doWriteInt(UNREGISTERED_TYPE_ID);
-                doWriteString(val.getClass().getComponentType().getName());
-            }
-
-            doWriteInt(val.length);
-
-            for (Object obj : val)
-                doWriteObject(obj, false);
-        }
-    }
-
-    /**
-     * @param col Collection.
-     * @throws PortableException In case of error.
-     */
-    void doWriteCollection(@Nullable Collection<?> col) throws 
PortableException {
-        if (col == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(COL);
-            doWriteInt(col.size());
-            doWriteByte(ctx.collectionType(col.getClass()));
-
-            for (Object obj : col)
-                doWriteObject(obj, false);
-        }
-    }
-
-    /**
-     * @param map Map.
-     * @throws PortableException In case of error.
-     */
-    void doWriteMap(@Nullable Map<?, ?> map) throws PortableException {
-        if (map == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(MAP);
-            doWriteInt(map.size());
-            doWriteByte(ctx.mapType(map.getClass()));
-
-            for (Map.Entry<?, ?> e : map.entrySet()) {
-                doWriteObject(e.getKey(), false);
-                doWriteObject(e.getValue(), false);
-            }
-        }
-    }
-
-    /**
-     * @param e Map entry.
-     * @throws PortableException In case of error.
-     */
-    void doWriteMapEntry(@Nullable Map.Entry<?, ?> e) throws PortableException 
{
-        if (e == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(MAP_ENTRY);
-            doWriteObject(e.getKey(), false);
-            doWriteObject(e.getValue(), false);
-        }
-    }
-
-    /**
-     * @param val Value.
-     */
-    void doWriteEnum(@Nullable Enum<?> val) {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            GridPortableContext.Type type = ctx.typeId(val.getClass());
-
-            doWriteByte(ENUM);
-
-            if (type.registered())
-                doWriteInt(type.id());
-            else {
-                doWriteInt(UNREGISTERED_TYPE_ID);
-                doWriteString(val.getClass().getName());
-            }
-
-            doWriteInt(val.ordinal());
-        }
-    }
-
-    /**
-     * @param val Array.
-     */
-    void doWriteEnumArray(@Nullable Object[] val) {
-        assert val == null || val.getClass().getComponentType().isEnum();
-
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            GridPortableContext.Type type = 
ctx.typeId(val.getClass().getComponentType());
-
-            doWriteByte(ENUM_ARR);
-
-            if (type.registered())
-                doWriteInt(type.id());
-            else {
-                doWriteInt(UNREGISTERED_TYPE_ID);
-                doWriteString(val.getClass().getComponentType().getName());
-            }
-
-            doWriteInt(val.length);
-
-            // TODO: Denis: Redundant data for each element of the array.
-            for (Object o : val)
-                doWriteEnum((Enum<?>)o);
-        }
-    }
-
-    /**
-     * @param val Class.
-     */
-    void doWriteClass(@Nullable Class val) {
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            GridPortableContext.Type type = ctx.typeId(val);
-
-            doWriteByte(CLASS);
-
-            if (type.registered())
-                doWriteInt(type.id());
-            else {
-                doWriteInt(UNREGISTERED_TYPE_ID);
-                doWriteString(val.getClass().getName());
-            }
-        }
-    }
-
-    /**
-     * @param po Portable object.
-     */
-    void doWritePortableObject(@Nullable GridPortableObjectImpl po) {
-        if (po == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(PORTABLE_OBJ);
-
-            byte[] poArr = po.array();
-
-            doWriteInt(poArr.length);
-
-            wCtx.out.writeByteArray(poArr);
-
-            doWriteInt(po.start());
-        }
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeByteField(@Nullable Byte val) {
-        doWriteInt(val != null ? 2 : 1);
-
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(BYTE);
-            doWriteByte(val);
-        }
-    }
-
-    /**
-     * @param val Class.
-     */
-    void writeClassField(@Nullable Class val) {
-        int lenPos = reserveAndMark(4);
-
-        doWriteClass(val);
-
-        writeDelta(lenPos);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeShortField(@Nullable Short val) {
-        doWriteInt(val != null ? 3 : 1);
-
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(SHORT);
-            doWriteShort(val);
-        }
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeIntField(@Nullable Integer val) {
-        doWriteInt(val != null ? 5 : 1);
-
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(INT);
-            doWriteInt(val);
-        }
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeLongField(@Nullable Long val) {
-        doWriteInt(val != null ? 9 : 1);
-
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(LONG);
-            doWriteLong(val);
-        }
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeFloatField(@Nullable Float val) {
-        doWriteInt(val != null ? 5 : 1);
-
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(FLOAT);
-            doWriteFloat(val);
-        }
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeDoubleField(@Nullable Double val) {
-        doWriteInt(val != null ? 9 : 1);
-
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(DOUBLE);
-            doWriteDouble(val);
-        }
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeCharField(@Nullable Character val) {
-        doWriteInt(val != null ? 3 : 1);
-
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(CHAR);
-            doWriteChar(val);
-        }
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeBooleanField(@Nullable Boolean val) {
-        doWriteInt(val != null ? 2 : 1);
-
-        if (val == null)
-            doWriteByte(NULL);
-        else {
-            doWriteByte(BOOLEAN);
-            doWriteBoolean(val);
-        }
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeDecimalField(@Nullable BigDecimal val) {
-        int lenPos = reserveAndMark(4);
-
-        doWriteDecimal(val);
-
-        writeDelta(lenPos);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeStringField(@Nullable String val) {
-        int lenPos = reserveAndMark(4);
-
-        doWriteString(val);
-
-        writeDelta(lenPos);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeUuidField(@Nullable UUID val) {
-        doWriteInt(val != null ? 17 : 1);
-        doWriteUuid(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeDateField(@Nullable Date val) {
-        doWriteInt(val != null ? 13 : 1);
-        doWriteDate(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeTimestampField(@Nullable Timestamp val) {
-        doWriteInt(val != null ? 13 : 1);
-        doWriteTimestamp(val);
-    }
-
-    /**
-     * @param obj Object.
-     * @throws PortableException In case of error.
-     */
-    void writeObjectField(@Nullable Object obj) throws PortableException {
-        int lenPos = reserveAndMark(4);
-
-        doWriteObject(obj, false);
-
-        writeDelta(lenPos);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeByteArrayField(@Nullable byte[] val) {
-        doWriteInt(val != null ? 5 + val.length : 1);
-        doWriteByteArray(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeShortArrayField(@Nullable short[] val) {
-        doWriteInt(val != null ? 5 + (val.length << 1) : 1);
-        doWriteShortArray(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeIntArrayField(@Nullable int[] val) {
-        doWriteInt(val != null ? 5 + (val.length << 2) : 1);
-        doWriteIntArray(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeLongArrayField(@Nullable long[] val) {
-        doWriteInt(val != null ? 5 + (val.length << 3) : 1);
-        doWriteLongArray(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeFloatArrayField(@Nullable float[] val) {
-        doWriteInt(val != null ? 5 + (val.length << 2) : 1);
-        doWriteFloatArray(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeDoubleArrayField(@Nullable double[] val) {
-        doWriteInt(val != null ? 5 + (val.length << 3) : 1);
-        doWriteDoubleArray(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeCharArrayField(@Nullable char[] val) {
-        doWriteInt(val != null ? 5 + (val.length << 1) : 1);
-        doWriteCharArray(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeBooleanArrayField(@Nullable boolean[] val) {
-        doWriteInt(val != null ? 5 + val.length : 1);
-        doWriteBooleanArray(val);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeDecimalArrayField(@Nullable BigDecimal[] val) {
-        int lenPos = reserveAndMark(4);
-
-        doWriteDecimalArray(val);
-
-        writeDelta(lenPos);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeStringArrayField(@Nullable String[] val) {
-        int lenPos = reserveAndMark(4);
-
-        doWriteStringArray(val);
-
-        writeDelta(lenPos);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeUuidArrayField(@Nullable UUID[] val) {
-        int lenPos = reserveAndMark(4);
-
-        doWriteUuidArray(val);
-
-        writeDelta(lenPos);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeDateArrayField(@Nullable Date[] val) {
-        int lenPos = reserveAndMark(4);
-
-        doWriteDateArray(val);
-
-        writeDelta(lenPos);
-    }
-
-    /**
-     * @param val Value.
-     * @throws PortableException In case of error.
-     */
-    void writeObjectArrayField(@Nullable Object[] val) throws 
PortableException {
-        int lenPos = reserveAndMark(4);
-
-        doWriteObjectArray(val);
-
-        writeDelta(lenPos);
-    }
-
-    /**
-     * @param col Collection.
-     * @throws PortableException In case of error.
-     */
-    void writeCollectionField(@Nullable Collection<?> col) throws 
PortableException {
-        int lenPos = reserveAndMark(4);
-
-        doWriteCollection(col);
-
-        writeDelta(lenPos);
-    }
-
-    /**
-     * @param map Map.
-     * @throws PortableException In case of error.
-     */
-    void writeMapField(@Nullable Map<?, ?> map) throws PortableException {
-        int lenPos = reserveAndMark(4);
-
-        doWriteMap(map);
-
-        writeDelta(lenPos);
-    }
-
-    /**
-     * @param e Map entry.
-     * @throws PortableException In case of error.
-     */
-    void writeMapEntryField(@Nullable Map.Entry<?, ?> e) throws 
PortableException {
-        int lenPos = reserveAndMark(4);
-
-        doWriteMapEntry(e);
-
-        writeDelta(lenPos);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeEnumField(@Nullable Enum<?> val) {
-        int lenPos = reserveAndMark(4);
-
-        doWriteEnum(val);
-
-        writeDelta(lenPos);
-    }
-
-    /**
-     * @param val Value.
-     */
-    void writeEnumArrayField(@Nullable Object[] val) {
-        int lenPos = reserveAndMark(4);
-
-        doWriteEnumArray(val);
-
-        writeDelta(lenPos);
-    }
-
-    /**
-     * @param po Portable object.
-     * @throws PortableException In case of error.
-     */
-    void writePortableObjectField(@Nullable GridPortableObjectImpl po) throws 
PortableException {
-        int lenPos = reserveAndMark(4);
-
-        doWritePortableObject(po);
-
-        writeDelta(lenPos);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeByte(String fieldName, byte val) throws 
PortableException {
-        writeFieldId(fieldName, BYTE);
-        writeByteField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeByte(byte val) throws PortableException {
-        doWriteByte(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeShort(String fieldName, short val) throws 
PortableException {
-        writeFieldId(fieldName, SHORT);
-        writeShortField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeShort(short val) throws PortableException {
-        doWriteShort(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeInt(String fieldName, int val) throws 
PortableException {
-        writeFieldId(fieldName, INT);
-        writeIntField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeInt(int val) throws PortableException {
-        doWriteInt(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeLong(String fieldName, long val) throws 
PortableException {
-        writeFieldId(fieldName, LONG);
-        writeLongField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeLong(long val) throws PortableException {
-        doWriteLong(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeFloat(String fieldName, float val) throws 
PortableException {
-        writeFieldId(fieldName, FLOAT);
-        writeFloatField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeFloat(float val) throws PortableException {
-        doWriteFloat(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeDouble(String fieldName, double val) throws 
PortableException {
-        writeFieldId(fieldName, DOUBLE);
-        writeDoubleField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeDouble(double val) throws PortableException {
-        doWriteDouble(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeChar(String fieldName, char val) throws 
PortableException {
-        writeFieldId(fieldName, CHAR);
-        writeCharField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeChar(char val) throws PortableException {
-        doWriteChar(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeBoolean(String fieldName, boolean val) throws 
PortableException {
-        writeFieldId(fieldName, BOOLEAN);
-        writeBooleanField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeBoolean(boolean val) throws PortableException {
-        doWriteBoolean(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeDecimal(String fieldName, @Nullable BigDecimal 
val) throws PortableException {
-        writeFieldId(fieldName, DECIMAL);
-        writeDecimalField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeDecimal(@Nullable BigDecimal val) throws 
PortableException {
-        doWriteDecimal(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeString(String fieldName, @Nullable String val) 
throws PortableException {
-        writeFieldId(fieldName, STRING);
-        writeStringField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeString(@Nullable String val) throws 
PortableException {
-        doWriteString(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeUuid(String fieldName, @Nullable UUID val) 
throws PortableException {
-        writeFieldId(fieldName, UUID);
-        writeUuidField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeUuid(@Nullable UUID val) throws 
PortableException {
-        doWriteUuid(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeDate(String fieldName, @Nullable Date val) 
throws PortableException {
-        writeFieldId(fieldName, DATE);
-        writeDateField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeDate(@Nullable Date val) throws 
PortableException {
-        doWriteDate(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeTimestamp(String fieldName, @Nullable Timestamp 
val) throws PortableException {
-        writeFieldId(fieldName, DATE);
-        writeTimestampField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeTimestamp(@Nullable Timestamp val) throws 
PortableException {
-        doWriteTimestamp(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeObject(String fieldName, @Nullable Object obj) 
throws PortableException {
-        writeFieldId(fieldName, OBJ);
-        writeObjectField(obj);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeObject(@Nullable Object obj) throws 
PortableException {
-        doWriteObject(obj, false);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeObjectDetached(@Nullable Object obj) throws 
PortableException {
-        doWriteObject(obj, true);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeByteArray(String fieldName, @Nullable byte[] 
val) throws PortableException {
-        writeFieldId(fieldName, BYTE_ARR);
-        writeByteArrayField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeByteArray(@Nullable byte[] val) throws 
PortableException {
-        doWriteByteArray(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeShortArray(String fieldName, @Nullable short[] 
val) throws PortableException {
-        writeFieldId(fieldName, SHORT_ARR);
-        writeShortArrayField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeShortArray(@Nullable short[] val) throws 
PortableException {
-        doWriteShortArray(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeIntArray(String fieldName, @Nullable int[] val) 
throws PortableException {
-        writeFieldId(fieldName, INT_ARR);
-        writeIntArrayField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeIntArray(@Nullable int[] val) throws 
PortableException {
-        doWriteIntArray(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeLongArray(String fieldName, @Nullable long[] 
val) throws PortableException {
-        writeFieldId(fieldName, LONG_ARR);
-        writeLongArrayField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeLongArray(@Nullable long[] val) throws 
PortableException {
-        doWriteLongArray(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeFloatArray(String fieldName, @Nullable float[] 
val) throws PortableException {
-        writeFieldId(fieldName, FLOAT_ARR);
-        writeFloatArrayField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeFloatArray(@Nullable float[] val) throws 
PortableException {
-        doWriteFloatArray(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeDoubleArray(String fieldName, @Nullable 
double[] val)
-        throws PortableException {
-        writeFieldId(fieldName, DOUBLE_ARR);
-        writeDoubleArrayField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeDoubleArray(@Nullable double[] val) throws 
PortableException {
-        doWriteDoubleArray(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeCharArray(String fieldName, @Nullable char[] 
val) throws PortableException {
-        writeFieldId(fieldName, CHAR_ARR);
-        writeCharArrayField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeCharArray(@Nullable char[] val) throws 
PortableException {
-        doWriteCharArray(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeBooleanArray(String fieldName, @Nullable 
boolean[] val)
-        throws PortableException {
-        writeFieldId(fieldName, BOOLEAN_ARR);
-        writeBooleanArrayField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeBooleanArray(@Nullable boolean[] val) throws 
PortableException {
-        doWriteBooleanArray(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeDecimalArray(String fieldName, @Nullable 
BigDecimal[] val)
-        throws PortableException {
-        writeFieldId(fieldName, DECIMAL_ARR);
-        writeDecimalArrayField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeDecimalArray(@Nullable BigDecimal[] val) throws 
PortableException {
-        doWriteDecimalArray(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeStringArray(String fieldName, @Nullable 
String[] val)
-        throws PortableException {
-        writeFieldId(fieldName, STRING_ARR);
-        writeStringArrayField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeStringArray(@Nullable String[] val) throws 
PortableException {
-        doWriteStringArray(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeUuidArray(String fieldName, @Nullable UUID[] 
val) throws PortableException {
-        writeFieldId(fieldName, UUID_ARR);
-        writeUuidArrayField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeUuidArray(@Nullable UUID[] val) throws 
PortableException {
-        doWriteUuidArray(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeDateArray(String fieldName, @Nullable Date[] 
val) throws PortableException {
-        writeFieldId(fieldName, DATE_ARR);
-        writeDateArrayField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeDateArray(@Nullable Date[] val) throws 
PortableException {
-        doWriteDateArray(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeObjectArray(String fieldName, @Nullable 
Object[] val) throws PortableException {
-        writeFieldId(fieldName, OBJ_ARR);
-        writeObjectArrayField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeObjectArray(@Nullable Object[] val) throws 
PortableException {
-        doWriteObjectArray(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public <T> void writeCollection(String fieldName, @Nullable 
Collection<T> col)
-        throws PortableException {
-        writeFieldId(fieldName, COL);
-        writeCollectionField(col);
-    }
-
-    /** {@inheritDoc} */
-    @Override public <T> void writeCollection(@Nullable Collection<T> col) 
throws PortableException {
-        doWriteCollection(col);
-    }
-
-    /** {@inheritDoc} */
-    @Override public <K, V> void writeMap(String fieldName, @Nullable Map<K, 
V> map)
-        throws PortableException {
-        writeFieldId(fieldName, MAP);
-        writeMapField(map);
-    }
-
-    /** {@inheritDoc} */
-    @Override public <K, V> void writeMap(@Nullable Map<K, V> map) throws 
PortableException {
-        doWriteMap(map);
-    }
-
-    /** {@inheritDoc} */
-    @Override public <T extends Enum<?>> void writeEnum(String fieldName, T 
val) throws PortableException {
-        writeFieldId(fieldName, ENUM);
-        writeEnumField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public <T extends Enum<?>> void writeEnum(T val) throws 
PortableException {
-        doWriteEnum(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public <T extends Enum<?>> void writeEnumArray(String fieldName, 
T[] val) throws PortableException {
-        writeFieldId(fieldName, ENUM_ARR);
-        writeEnumArrayField(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public <T extends Enum<?>> void writeEnumArray(T[] val) throws 
PortableException {
-        doWriteEnumArray(val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public PortableRawWriter rawWriter() {
-        if (allowFields) {
-            wCtx.out.writeInt(start + RAW_DATA_OFF_POS, wCtx.out.position() - 
start);
-
-            allowFields = false;
-        }
-
-        return this;
-    }
-
-    /** {@inheritDoc} */
-    @Override public GridPortableOutputStream out() {
-        return wCtx.out;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeBytes(String s) throws IOException {
-        int len = s.length();
-
-        writeInt(len);
-
-        for (int i = 0; i < len; i++)
-            writeByte(s.charAt(i));
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeChars(String s) throws IOException {
-        int len = s.length();
-
-        writeInt(len);
-
-        for (int i = 0; i < len; i++)
-            writeChar(s.charAt(i));
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeUTF(String s) throws IOException {
-        writeString(s);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeByte(int v) throws IOException {
-        doWriteByte((byte)v);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeShort(int v) throws IOException {
-        doWriteShort((short)v);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeChar(int v) throws IOException {
-        doWriteChar((char)v);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void write(int b) throws IOException {
-        doWriteByte((byte)b);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void flush() throws IOException {
-        // No-op.
-    }
-
-    /**
-     * Reserve a room for an integer.
-     *
-     * @return Position in the stream where value is to be written.
-     */
-    public int reserveInt() {
-        return reserve(LEN_INT);
-    }
-
-    /**
-     * Write int value at the specific position.
-     *
-     * @param pos Position.
-     * @param val Value.
-     * @throws PortableException If failed.
-     */
-    public void writeInt(int pos, int val) throws PortableException {
-        wCtx.out.writeInt(pos, val);
-    }
-
-    /**
-     * @param fieldName Field name.
-     * @throws PortableException If fields are not allowed.
-     */
-    private void writeFieldId(String fieldName, byte fieldType) throws 
PortableException {
-        A.notNull(fieldName, "fieldName");
-
-        if (!allowFields)
-            throw new PortableException("Individual field can't be written 
after raw writer is acquired " +
-                "via rawWriter() method. Consider fixing serialization logic 
for class: " + cls.getName());
-
-        int id = ctx.fieldId(typeId, fieldName);
-
-        if (metaEnabled)
-            metaHashSum = 31 * metaHashSum + (id + fieldType);
-
-        doWriteInt(id);
-    }
-
-    /**
-     * Create new writer with same context.
-     * @param typeId type
-     * @return New writer.
-     */
-    GridPortableWriterExImpl newWriter(int typeId) {
-        GridPortableWriterExImpl res = new GridPortableWriterExImpl(ctx, wCtx);
-
-        res.typeId = typeId;
-
-        return res;
-    }
-
-    /**
-     * @return Portable context.
-     */
-    GridPortableContext context() {
-        return ctx;
-    }
-
-    /** */
-    private static class WriterContext {
-        /** */
-        private Map<Object, Integer> handles = new IdentityHashMap<>();
-
-        /** Output stream. */
-        private GridPortableOutputStream out;
-
-        /**
-         * Constructor.
-         *
-         * @param out Output stream.
-         * @param handles Handles.
-         */
-        private WriterContext(GridPortableOutputStream out, Map<Object, 
Integer> handles) {
-            this.out = out;
-            this.handles = handles == null ? new IdentityHashMap<Object, 
Integer>() : handles;
-        }
-
-        /**
-         * @param obj Object.
-         * @return Handle.
-         */
-        private int handle(Object obj) {
-            assert obj != null;
-
-            Integer h = handles.get(obj);
-
-            if (h != null)
-                return out.position() - h;
-            else {
-                handles.put(obj, out.position());
-
-                return -1;
-            }
-        }
-
-        /**
-         *
-         */
-        private void resetHandles() {
-            handles = new IdentityHashMap<>();
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/4662feca/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
new file mode 100644
index 0000000..83b3050
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/portable/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;
+
+/**
+ *
+ */
+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/incubator-ignite/blob/4662feca/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
new file mode 100644
index 0000000..eec68a5
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderEnum.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;
+
+import org.apache.ignite.internal.util.typedef.internal.*;
+import org.apache.ignite.portable.*;
+
+/**
+ *
+ */
+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: GG-10396 - 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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/4662feca/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
new file mode 100644
index 0000000..d471748
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderImpl.java
@@ -0,0 +1,519 @@
+/*
+ * 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.*;
+import org.apache.ignite.internal.util.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+import org.apache.ignite.portable.*;
+
+import org.jetbrains.annotations.*;
+
+import java.util.*;
+
+import static org.apache.ignite.internal.portable.GridPortableMarshaller.*;
+
+/**
+ *
+ */
+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: GG-10396 - 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;
+    }
+}

Reply via email to