You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ag...@apache.org on 2015/10/30 11:44:36 UTC

[08/19] ignite git commit: ignite-950-new WIP

http://git-wip-us.apache.org/repos/asf/ignite/blob/35b6d61f/modules/core/src/main/java/org/apache/ignite/portable/PortableObject.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/portable/PortableObject.java b/modules/core/src/main/java/org/apache/ignite/portable/PortableObject.java
deleted file mode 100644
index 66b8f76..0000000
--- a/modules/core/src/main/java/org/apache/ignite/portable/PortableObject.java
+++ /dev/null
@@ -1,154 +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.portable;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.TreeMap;
-import org.apache.ignite.IgnitePortables;
-import org.apache.ignite.marshaller.portable.PortableMarshaller;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Wrapper for portable object in portable binary format. Once an object is defined as portable,
- * Ignite will always store it in memory in the portable (i.e. binary) format.
- * User can choose to work either with the portable format or with the deserialized form
- * (assuming that class definitions are present in the classpath).
- * <p>
- * <b>NOTE:</b> user does not need to (and should not) implement this interface directly.
- * <p>
- * To work with the portable format directly, user should create a cache projection
- * over {@code PortableObject} class and then retrieve individual fields as needed:
- * <pre name=code class=java>
- * IgniteCache&lt;PortableObject, PortableObject&gt; prj = cache.withKeepPortable();
- *
- * // Convert instance of MyKey to portable format.
- * // We could also use GridPortableBuilder to create the key in portable format directly.
- * PortableObject key = grid.portables().toPortable(new MyKey());
- *
- * PortableObject val = prj.get(key);
- *
- * String field = val.field("myFieldName");
- * </pre>
- * Alternatively, if we have class definitions in the classpath, we may choose to work with deserialized
- * typed objects at all times. In this case we do incur the deserialization cost. However, if
- * {@link PortableMarshaller#isKeepDeserialized()} is {@code true} then Ignite will only deserialize on the first access
- * and will cache the deserialized object, so it does not have to be deserialized again:
- * <pre name=code class=java>
- * IgniteCache&lt;MyKey.class, MyValue.class&gt; cache = grid.cache(null);
- *
- * MyValue val = cache.get(new MyKey());
- *
- * // Normal java getter.
- * String fieldVal = val.getMyFieldName();
- * </pre>
- * <h1 class="header">Working With Maps and Collections</h1>
- * All maps and collections in the portable objects are serialized automatically. When working
- * with different platforms, e.g. C++ or .NET, Ignite will automatically pick the most
- * adequate collection or map in either language. For example, {@link ArrayList} in Java will become
- * {@code List} in C#, {@link LinkedList} in Java is {@link LinkedList} in C#, {@link HashMap}
- * in Java is {@code Dictionary} in C#, and {@link TreeMap} in Java becomes {@code SortedDictionary}
- * in C#, etc.
- * <h1 class="header">Dynamic Structure Changes</h1>
- * Since objects are always cached in the portable binary format, server does not need to
- * be aware of the class definitions. Moreover, if class definitions are not present or not
- * used on the server, then clients can continuously change the structure of the portable
- * objects without having to restart the cluster. For example, if one client stores a
- * certain class with fields A and B, and another client stores the same class with
- * fields B and C, then the server-side portable object will have the fields A, B, and C.
- * As the structure of a portable object changes, the new fields become available for SQL queries
- * automatically.
- * <h1 class="header">Building Portable Objects</h1>
- * Ignite comes with {@link PortableBuilder} which allows to build portable objects dynamically:
- * <pre name=code class=java>
- * PortableBuilder builder = Ignition.ignite().portables().builder("org.project.MyObject");
- *
- * builder.setField("fieldA", "A");
- * builder.setField("fieldB", "B");
- *
- * PortableObject portableObj = builder.build();
- * </pre>
- * For the cases when class definition is present
- * in the class path, it is also possible to populate a standard POJO and then
- * convert it to portable format, like so:
- * <pre name=code class=java>
- * MyObject obj = new MyObject();
- *
- * obj.setFieldA("A");
- * obj.setFieldB(123);
- *
- * PortableObject portableObj = Ignition.ignite().portables().toPortable(obj);
- * </pre>
- * <h1 class="header">Portable Metadata</h1>
- * Even though Ignite portable protocol only works with hash codes for type and field names
- * to achieve better performance, Ignite provides metadata for all portable types which
- * can be queried ar runtime via any of the {@link IgnitePortables#metadata(Class)}
- * methods. Having metadata also allows for proper formatting of {@code PortableObject.toString()} method,
- * even when portable objects are kept in binary format only, which may be necessary for audit reasons.
- */
-public interface PortableObject extends Serializable, Cloneable {
-    /**
-     * Gets portable object type ID.
-     *
-     * @return Type ID.
-     */
-    public int typeId();
-
-    /**
-     * Gets meta data for this portable object.
-     *
-     * @return Meta data.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public PortableMetadata metaData() throws PortableException;
-
-    /**
-     * Gets field value.
-     *
-     * @param fieldName Field name.
-     * @return Field value.
-     * @throws PortableException In case of any other error.
-     */
-    @Nullable public <F> F field(String fieldName) throws PortableException;
-
-    /**
-     * Checks whether field is set.
-     *
-     * @param fieldName Field name.
-     * @return {@code true} if field is set.
-     */
-    public boolean hasField(String fieldName);
-
-    /**
-     * Gets fully deserialized instance of portable object.
-     *
-     * @return Fully deserialized instance of portable object.
-     * @throws PortableInvalidClassException If class doesn't exist.
-     * @throws PortableException In case of any other error.
-     */
-    @Nullable public <T> T deserialize() throws PortableException;
-
-    /**
-     * Copies this portable object.
-     *
-     * @return Copy of this portable object.
-     */
-    public PortableObject clone() throws CloneNotSupportedException;
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/35b6d61f/modules/core/src/main/java/org/apache/ignite/portable/PortableReader.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/portable/PortableReader.java b/modules/core/src/main/java/org/apache/ignite/portable/PortableReader.java
deleted file mode 100644
index f2b1cda..0000000
--- a/modules/core/src/main/java/org/apache/ignite/portable/PortableReader.java
+++ /dev/null
@@ -1,291 +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.portable;
-
-import java.math.BigDecimal;
-import java.sql.Timestamp;
-import java.util.Collection;
-import java.util.Date;
-import java.util.Map;
-import java.util.UUID;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Reader for portable objects used in {@link PortableMarshalAware} implementations.
- * Useful for the cases when user wants a fine-grained control over serialization.
- * <p>
- * Note that Ignite never writes full strings for field or type names. Instead,
- * for performance reasons, Ignite writes integer hash codes for type and field names.
- * It has been tested that hash code conflicts for the type names or the field names
- * within the same type are virtually non-existent and, to gain performance, it is safe
- * to work with hash codes. For the cases when hash codes for different types or fields
- * actually do collide, Ignite provides {@link PortableIdMapper} which
- * allows to override the automatically generated hash code IDs for the type and field names.
- */
-public interface PortableReader {
-    /**
-     * @param fieldName Field name.
-     * @return Byte value.
-     * @throws PortableException In case of error.
-     */
-    public byte readByte(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Short value.
-     * @throws PortableException In case of error.
-     */
-    public short readShort(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Integer value.
-     * @throws PortableException In case of error.
-     */
-    public int readInt(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Long value.
-     * @throws PortableException In case of error.
-     */
-    public long readLong(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @throws PortableException In case of error.
-     * @return Float value.
-     */
-    public float readFloat(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Double value.
-     * @throws PortableException In case of error.
-     */
-    public double readDouble(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Char value.
-     * @throws PortableException In case of error.
-     */
-    public char readChar(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Boolean value.
-     * @throws PortableException In case of error.
-     */
-    public boolean readBoolean(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Decimal value.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public BigDecimal readDecimal(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return String value.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public String readString(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return UUID.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public UUID readUuid(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Date.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public Date readDate(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Timestamp.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public Timestamp readTimestamp(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Object.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public <T> T readObject(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Byte array.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public byte[] readByteArray(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Short array.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public short[] readShortArray(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Integer array.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public int[] readIntArray(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Long array.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public long[] readLongArray(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Float array.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public float[] readFloatArray(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Byte array.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public double[] readDoubleArray(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Char array.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public char[] readCharArray(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Boolean array.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public boolean[] readBooleanArray(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Decimal array.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public BigDecimal[] readDecimalArray(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return String array.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public String[] readStringArray(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return UUID array.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public UUID[] readUuidArray(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Date array.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public Date[] readDateArray(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Timestamp array.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public Timestamp[] readTimestampArray(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Object array.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public Object[] readObjectArray(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Collection.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public <T> Collection<T> readCollection(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param colCls Collection class.
-     * @return Collection.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public <T> Collection<T> readCollection(String fieldName, Class<? extends Collection<T>> colCls)
-        throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Map.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public <K, V> Map<K, V> readMap(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param mapCls Map class.
-     * @return Map.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public <K, V> Map<K, V> readMap(String fieldName, Class<? extends Map<K, V>> mapCls)
-        throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Value.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public <T extends Enum<?>> T readEnum(String fieldName) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @return Value.
-     * @throws PortableException In case of error.
-     */
-    @Nullable public <T extends Enum<?>> T[] readEnumArray(String fieldName) throws PortableException;
-
-    /**
-     * Gets raw reader. Raw reader does not use field name hash codes, therefore,
-     * making the format even more compact. However, if the raw reader is used,
-     * dynamic structure changes to the portable objects are not supported.
-     *
-     * @return Raw reader.
-     */
-    public PortableRawReader rawReader();
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/35b6d61f/modules/core/src/main/java/org/apache/ignite/portable/PortableSerializer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/portable/PortableSerializer.java b/modules/core/src/main/java/org/apache/ignite/portable/PortableSerializer.java
deleted file mode 100644
index 90ee562..0000000
--- a/modules/core/src/main/java/org/apache/ignite/portable/PortableSerializer.java
+++ /dev/null
@@ -1,49 +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.portable;
-
-import org.apache.ignite.marshaller.portable.PortableMarshaller;
-
-/**
- * Interface that allows to implement custom serialization logic for portable objects.
- * Can be used instead of {@link PortableMarshalAware} in case if the class
- * cannot be changed directly.
- * <p>
- * Portable serializer can be configured for all portable objects via
- * {@link PortableMarshaller#getSerializer()} method, or for a specific
- * portable type via {@link PortableTypeConfiguration#getSerializer()} method.
- */
-public interface PortableSerializer {
-    /**
-     * Writes fields to provided writer.
-     *
-     * @param obj Empty object.
-     * @param writer Portable object writer.
-     * @throws PortableException In case of error.
-     */
-    public void writePortable(Object obj, PortableWriter writer) throws PortableException;
-
-    /**
-     * Reads fields from provided reader.
-     *
-     * @param obj Empty object
-     * @param reader Portable object reader.
-     * @throws PortableException In case of error.
-     */
-    public void readPortable(Object obj, PortableReader reader) throws PortableException;
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/35b6d61f/modules/core/src/main/java/org/apache/ignite/portable/PortableTypeConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/portable/PortableTypeConfiguration.java b/modules/core/src/main/java/org/apache/ignite/portable/PortableTypeConfiguration.java
deleted file mode 100644
index 68f0514..0000000
--- a/modules/core/src/main/java/org/apache/ignite/portable/PortableTypeConfiguration.java
+++ /dev/null
@@ -1,177 +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.portable;
-
-import java.sql.Timestamp;
-import java.util.Collection;
-import org.apache.ignite.internal.util.typedef.internal.S;
-import org.apache.ignite.marshaller.portable.PortableMarshaller;
-
-/**
- * Defines configuration properties for a specific portable type. Providing per-type
- * configuration is optional, as it is generally enough, and also optional, to provide global portable
- * configuration using {@link PortableMarshaller#setClassNames(Collection)}.
- * However, this class allows you to change configuration properties for a specific
- * portable type without affecting configuration for other portable types.
- * <p>
- * Per-type portable configuration can be specified in {@link PortableMarshaller#getTypeConfigurations()} method.
- */
-public class PortableTypeConfiguration {
-    /** Class name. */
-    private String clsName;
-
-    /** ID mapper. */
-    private PortableIdMapper idMapper;
-
-    /** Serializer. */
-    private PortableSerializer serializer;
-
-    /** Meta data enabled flag. */
-    private Boolean metaDataEnabled;
-
-    /** Keep deserialized flag. */
-    private Boolean keepDeserialized;
-
-    /** Affinity key field name. */
-    private String affKeyFieldName;
-
-    /**
-     */
-    public PortableTypeConfiguration() {
-        // No-op.
-    }
-
-    /**
-     * @param clsName Class name.
-     */
-    public PortableTypeConfiguration(String clsName) {
-        this.clsName = clsName;
-    }
-
-    /**
-     * Gets type name.
-     *
-     * @return Type name.
-     */
-    public String getClassName() {
-        return clsName;
-    }
-
-    /**
-     * Sets type name.
-     *
-     * @param clsName Type name.
-     */
-    public void setClassName(String clsName) {
-        this.clsName = clsName;
-    }
-
-    /**
-     * Gets ID mapper.
-     *
-     * @return ID mapper.
-     */
-    public PortableIdMapper getIdMapper() {
-        return idMapper;
-    }
-
-    /**
-     * Sets ID mapper.
-     *
-     * @param idMapper ID mapper.
-     */
-    public void setIdMapper(PortableIdMapper idMapper) {
-        this.idMapper = idMapper;
-    }
-
-    /**
-     * Gets serializer.
-     *
-     * @return Serializer.
-     */
-    public PortableSerializer getSerializer() {
-        return serializer;
-    }
-
-    /**
-     * Sets serializer.
-     *
-     * @param serializer Serializer.
-     */
-    public void setSerializer(PortableSerializer serializer) {
-        this.serializer = serializer;
-    }
-
-    /**
-     * Defines whether meta data is collected for this type. If provided, this value will override
-     * {@link PortableMarshaller#isMetaDataEnabled()} property.
-     *
-     * @return Whether meta data is collected.
-     */
-    public Boolean isMetaDataEnabled() {
-        return metaDataEnabled;
-    }
-
-    /**
-     * @param metaDataEnabled Whether meta data is collected.
-     */
-    public void setMetaDataEnabled(Boolean metaDataEnabled) {
-        this.metaDataEnabled = metaDataEnabled;
-    }
-
-    /**
-     * Defines whether {@link PortableObject} should cache deserialized instance. If provided,
-     * this value will override {@link PortableMarshaller#isKeepDeserialized()}
-     * property.
-     *
-     * @return Whether deserialized value is kept.
-     */
-    public Boolean isKeepDeserialized() {
-        return keepDeserialized;
-    }
-
-    /**
-     * @param keepDeserialized Whether deserialized value is kept.
-     */
-    public void setKeepDeserialized(Boolean keepDeserialized) {
-        this.keepDeserialized = keepDeserialized;
-    }
-
-    /**
-     * Gets affinity key field name.
-     *
-     * @return Affinity key field name.
-     */
-    public String getAffinityKeyFieldName() {
-        return affKeyFieldName;
-    }
-
-    /**
-     * Sets affinity key field name.
-     *
-     * @param affKeyFieldName Affinity key field name.
-     */
-    public void setAffinityKeyFieldName(String affKeyFieldName) {
-        this.affKeyFieldName = affKeyFieldName;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(PortableTypeConfiguration.class, this, super.toString());
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/35b6d61f/modules/core/src/main/java/org/apache/ignite/portable/PortableWriter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/portable/PortableWriter.java b/modules/core/src/main/java/org/apache/ignite/portable/PortableWriter.java
deleted file mode 100644
index 99bd5c6..0000000
--- a/modules/core/src/main/java/org/apache/ignite/portable/PortableWriter.java
+++ /dev/null
@@ -1,273 +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.portable;
-
-import java.math.BigDecimal;
-import java.sql.Timestamp;
-import java.util.Collection;
-import java.util.Date;
-import java.util.Map;
-import java.util.UUID;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Writer for portable object used in {@link PortableMarshalAware} implementations.
- * Useful for the cases when user wants a fine-grained control over serialization.
- * <p>
- * Note that Ignite never writes full strings for field or type names. Instead,
- * for performance reasons, Ignite writes integer hash codes for type and field names.
- * It has been tested that hash code conflicts for the type names or the field names
- * within the same type are virtually non-existent and, to gain performance, it is safe
- * to work with hash codes. For the cases when hash codes for different types or fields
- * actually do collide, Ignite provides {@link PortableIdMapper} which
- * allows to override the automatically generated hash code IDs for the type and field names.
- */
-public interface PortableWriter {
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeByte(String fieldName, byte val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeShort(String fieldName, short val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeInt(String fieldName, int val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeLong(String fieldName, long val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeFloat(String fieldName, float val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeDouble(String fieldName, double val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeChar(String fieldName, char val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeBoolean(String fieldName, boolean val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeDecimal(String fieldName, @Nullable BigDecimal val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeString(String fieldName, @Nullable String val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val UUID to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeUuid(String fieldName, @Nullable UUID val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Date to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeDate(String fieldName, @Nullable Date val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Timestamp to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeTimestamp(String fieldName, @Nullable Timestamp val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param obj Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeObject(String fieldName, @Nullable Object obj) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeByteArray(String fieldName, @Nullable byte[] val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeShortArray(String fieldName, @Nullable short[] val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeIntArray(String fieldName, @Nullable int[] val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeLongArray(String fieldName, @Nullable long[] val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeFloatArray(String fieldName, @Nullable float[] val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeDoubleArray(String fieldName, @Nullable double[] val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeCharArray(String fieldName, @Nullable char[] val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeBooleanArray(String fieldName, @Nullable boolean[] val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeDecimalArray(String fieldName, @Nullable BigDecimal[] val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeStringArray(String fieldName, @Nullable String[] val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeUuidArray(String fieldName, @Nullable UUID[] val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeDateArray(String fieldName, @Nullable Date[] val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeTimestampArray(String fieldName, @Nullable Timestamp[] val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public void writeObjectArray(String fieldName, @Nullable Object[] val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param col Collection to write.
-     * @throws PortableException In case of error.
-     */
-    public <T> void writeCollection(String fieldName, @Nullable Collection<T> col) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param map Map to write.
-     * @throws PortableException In case of error.
-     */
-    public <K, V> void writeMap(String fieldName, @Nullable Map<K, V> map) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public <T extends Enum<?>> void writeEnum(String fieldName, T val) throws PortableException;
-
-    /**
-     * @param fieldName Field name.
-     * @param val Value to write.
-     * @throws PortableException In case of error.
-     */
-    public <T extends Enum<?>> void writeEnumArray(String fieldName, T[] val) throws PortableException;
-
-    /**
-     * Gets raw writer. Raw writer does not write field name hash codes, therefore,
-     * making the format even more compact. However, if the raw writer is used,
-     * dynamic structure changes to the portable objects are not supported.
-     *
-     * @return Raw writer.
-     */
-    public PortableRawWriter rawWriter();
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/35b6d61f/modules/core/src/main/java/org/apache/ignite/portable/package-info.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/portable/package-info.java b/modules/core/src/main/java/org/apache/ignite/portable/package-info.java
deleted file mode 100644
index 0105b15..0000000
--- a/modules/core/src/main/java/org/apache/ignite/portable/package-info.java
+++ /dev/null
@@ -1,22 +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 description. -->
- * Contains portable objects API classes.
- */
-package org.apache.ignite.portable;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/35b6d61f/modules/core/src/test/java/org/apache/ignite/internal/portable/GridIgniteObjectBuilderAdditionalSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/GridIgniteObjectBuilderAdditionalSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/GridIgniteObjectBuilderAdditionalSelfTest.java
new file mode 100644
index 0000000..d9fbc1c
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/GridIgniteObjectBuilderAdditionalSelfTest.java
@@ -0,0 +1,1289 @@
+/*
+ * 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 com.google.common.collect.ImmutableMap;
+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;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteObjects;
+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.IgniteObjectBuilderImpl;
+import org.apache.ignite.internal.portable.mutabletest.GridIgniteObjectMarshalerAwareTestClass;
+import org.apache.ignite.internal.processors.cache.portable.CacheObjectPortableProcessorImpl;
+import org.apache.ignite.internal.processors.cache.portable.IgniteObjectsImpl;
+import org.apache.ignite.internal.util.lang.GridMapEntry;
+import org.apache.ignite.marshaller.portable.PortableMarshaller;
+import org.apache.ignite.igniteobject.IgniteObjectBuilder;
+import org.apache.ignite.igniteobject.IgniteObjectMetadata;
+import org.apache.ignite.igniteobject.IgniteObject;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Assert;
+
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+import static org.apache.ignite.internal.portable.mutabletest.GridPortableTestClasses.Address;
+import static org.apache.ignite.internal.portable.mutabletest.GridPortableTestClasses.AddressBook;
+import static org.apache.ignite.internal.portable.mutabletest.GridPortableTestClasses.Company;
+import static org.apache.ignite.internal.portable.mutabletest.GridPortableTestClasses.TestObjectAllTypes;
+import static org.apache.ignite.internal.portable.mutabletest.GridPortableTestClasses.TestObjectArrayList;
+import static org.apache.ignite.internal.portable.mutabletest.GridPortableTestClasses.TestObjectContainer;
+import static org.apache.ignite.internal.portable.mutabletest.GridPortableTestClasses.TestObjectEnum;
+import static org.apache.ignite.internal.portable.mutabletest.GridPortableTestClasses.TestObjectInner;
+import static org.apache.ignite.internal.portable.mutabletest.GridPortableTestClasses.TestObjectOuter;
+
+/**
+ *
+ */
+public class GridIgniteObjectBuilderAdditionalSelfTest extends GridCommonAbstractTest {
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        CacheConfiguration cacheCfg = new CacheConfiguration();
+
+        cacheCfg.setCacheMode(REPLICATED);
+
+        cfg.setCacheConfiguration(cacheCfg);
+
+        PortableMarshaller marsh = new PortableMarshaller();
+
+        marsh.setClassNames(Arrays.asList("org.apache.ignite.internal.portable.mutabletest.*"));
+
+        marsh.setConvertStringToBytes(useUtf8());
+
+        cfg.setMarshaller(marsh);
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        startGrids(1);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        jcache(0).clear();
+    }
+
+    /**
+     * @return Whether to use UTF8 strings.
+     */
+    protected boolean useUtf8() {
+        return true;
+    }
+
+    /**
+     * @return Portables API.
+     */
+    protected IgniteObjects portables() {
+        return grid(0).portables();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testSimpleTypeFieldRead() throws Exception {
+        TestObjectAllTypes exp = new TestObjectAllTypes();
+
+        exp.setDefaultData();
+
+        IgniteObjectBuilder mutPo = wrap(exp);
+
+        for (Field field : TestObjectAllTypes.class.getDeclaredFields()) {
+            Object expVal = field.get(exp);
+            Object actVal = mutPo.getField(field.getName());
+
+            switch (field.getName()) {
+                case "anEnum":
+                    assertEquals(((PortableBuilderEnum)actVal).getOrdinal(), ((Enum)expVal).ordinal());
+                    break;
+
+                case "enumArr": {
+                    PortableBuilderEnum[] actArr = (PortableBuilderEnum[])actVal;
+                    Enum[] expArr = (Enum[])expVal;
+
+                    assertEquals(expArr.length, actArr.length);
+
+                    for (int i = 0; i < actArr.length; i++)
+                        assertEquals(expArr[i].ordinal(), actArr[i].getOrdinal());
+
+                    break;
+                }
+
+                case "entry":
+                    assertEquals(((Map.Entry)expVal).getKey(), ((Map.Entry)actVal).getKey());
+                    assertEquals(((Map.Entry)expVal).getValue(), ((Map.Entry)actVal).getValue());
+                    break;
+
+                default:
+                    assertTrue(field.getName(), Objects.deepEquals(expVal, actVal));
+                    break;
+            }
+        }
+    }
+
+    /**
+     *
+     */
+    public void testSimpleTypeFieldSerialize() {
+        TestObjectAllTypes exp = new TestObjectAllTypes();
+
+        exp.setDefaultData();
+
+        IgniteObjectBuilderImpl mutPo = wrap(exp);
+
+        TestObjectAllTypes res = mutPo.build().deserialize();
+
+        GridTestUtils.deepEquals(exp, res);
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testSimpleTypeFieldOverride() throws Exception {
+        TestObjectAllTypes exp = new TestObjectAllTypes();
+
+        exp.setDefaultData();
+
+        IgniteObjectBuilderImpl mutPo = wrap(new TestObjectAllTypes());
+
+        for (Field field : TestObjectAllTypes.class.getDeclaredFields())
+            mutPo.setField(field.getName(), field.get(exp));
+
+        TestObjectAllTypes res = mutPo.build().deserialize();
+
+        GridTestUtils.deepEquals(exp, res);
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testSimpleTypeFieldSetNull() throws Exception {
+        TestObjectAllTypes exp = new TestObjectAllTypes();
+
+        exp.setDefaultData();
+
+        IgniteObjectBuilderImpl mutPo = wrap(exp);
+
+        for (Field field : TestObjectAllTypes.class.getDeclaredFields()) {
+            if (!field.getType().isPrimitive())
+                mutPo.setField(field.getName(), null);
+        }
+
+        TestObjectAllTypes res = mutPo.build().deserialize();
+
+        for (Field field : TestObjectAllTypes.class.getDeclaredFields()) {
+            if (!field.getType().isPrimitive())
+                assertNull(field.getName(), field.get(res));
+        }
+    }
+
+    /**
+     * @throws IgniteCheckedException If any error occurs.
+     */
+    public void testMakeCyclicDependency() throws IgniteCheckedException {
+        TestObjectOuter outer = new TestObjectOuter();
+        outer.inner = new TestObjectInner();
+
+        IgniteObjectBuilderImpl mutOuter = wrap(outer);
+
+        IgniteObjectBuilderImpl mutInner = mutOuter.getField("inner");
+
+        mutInner.setField("outer", mutOuter);
+        mutInner.setField("foo", mutInner);
+
+        TestObjectOuter res = mutOuter.build().deserialize();
+
+        assertEquals(res, res.inner.outer);
+        assertEquals(res.inner, res.inner.foo);
+    }
+
+    /**
+     *
+     */
+    public void testDateArrayModification() {
+        TestObjectAllTypes obj = new TestObjectAllTypes();
+
+        obj.dateArr =  new Date[] {new Date(11111), new Date(11111), new Date(11111)};
+
+        IgniteObjectBuilderImpl 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 testTimestampArrayModification() {
+        TestObjectAllTypes obj = new TestObjectAllTypes();
+
+        obj.tsArr = new Timestamp[] {new Timestamp(111222333), new Timestamp(222333444)};
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        Timestamp[] arr = mutObj.getField("tsArr");
+        arr[0] = new Timestamp(333444555);
+
+        TestObjectAllTypes res = mutObj.build().deserialize();
+
+        Assert.assertArrayEquals(new Timestamp[] {new Timestamp(333444555), new Timestamp(222333444)}, res.tsArr);
+    }
+
+    /**
+     *
+     */
+    public void testUUIDArrayModification() {
+        TestObjectAllTypes obj = new TestObjectAllTypes();
+
+        obj.uuidArr = new UUID[] {new UUID(1, 1), new UUID(1, 1), new UUID(1, 1)};
+
+        IgniteObjectBuilderImpl 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)};
+
+        IgniteObjectBuilderImpl 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};
+
+        IgniteObjectBuilderImpl 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'};
+
+        IgniteObjectBuilderImpl 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};
+
+        IgniteObjectBuilderImpl 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};
+
+        IgniteObjectBuilderImpl 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};
+
+        IgniteObjectBuilderImpl 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};
+
+        IgniteObjectBuilderImpl 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};
+
+        IgniteObjectBuilderImpl 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};
+
+        IgniteObjectBuilderImpl 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"};
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        String[] arr = mutObj.getField("strArr");
+        arr[0] = "b";
+
+        TestObjectAllTypes res = mutObj.build().deserialize();
+
+        Assert.assertArrayEquals(new String[] {"b", "a", "a"}, res.strArr);
+    }
+
+    /**
+     *
+     */
+    public void testModifyObjectArray() {
+        TestObjectContainer obj = new TestObjectContainer();
+        obj.foo = new Object[] {"a"};
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        Object[] arr = mutObj.getField("foo");
+
+        Assert.assertArrayEquals(new Object[] {"a"}, arr);
+
+        arr[0] = "b";
+
+        TestObjectContainer res = mutObj.build().deserialize();
+
+        Assert.assertArrayEquals(new Object[] {"b"}, (Object[])res.foo);
+    }
+
+    /**
+     *
+     */
+    public void testOverrideObjectArrayField() {
+        IgniteObjectBuilderImpl mutObj = wrap(new TestObjectContainer());
+
+        Object[] createdArr = {mutObj, "a", 1, new String[] {"s", "s"}, new byte[] {1, 2}, new UUID(3, 0)};
+
+        mutObj.setField("foo", createdArr.clone());
+
+        TestObjectContainer res = mutObj.build().deserialize();
+
+        createdArr[0] = res;
+
+        assertTrue(Objects.deepEquals(createdArr, res.foo));
+    }
+
+    /**
+     *
+     */
+    public void testDeepArray() {
+        TestObjectContainer obj = new TestObjectContainer();
+        obj.foo = new Object[] {new Object[] {"a", obj}};
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        Object[] arr = (Object[])mutObj.<Object[]>getField("foo")[0];
+
+        assertEquals("a", arr[0]);
+        assertSame(mutObj, arr[1]);
+
+        arr[0] = mutObj;
+
+        TestObjectContainer res = mutObj.build().deserialize();
+
+        arr = (Object[])((Object[])res.foo)[0];
+
+        assertSame(arr[0], res);
+        assertSame(arr[0], arr[1]);
+    }
+
+    /**
+     *
+     */
+    public void testArrayListRead() {
+        TestObjectContainer obj = new TestObjectContainer();
+        obj.foo = Lists.newArrayList(obj, "a");
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        List<Object> list = mutObj.getField("foo");
+
+        assert list.equals(Lists.newArrayList(mutObj, "a"));
+    }
+
+    /**
+     *
+     */
+    public void testArrayListOverride() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        ArrayList<Object> list = Lists.newArrayList(mutObj, "a", Lists.newArrayList(1, 2));
+
+        mutObj.setField("foo", list);
+
+        TestObjectContainer res = mutObj.build().deserialize();
+
+        list.set(0, res);
+
+        assertNotSame(list, res.foo);
+        assertEquals(list, res.foo);
+    }
+
+    /**
+     *
+     */
+    public void testArrayListModification() {
+        TestObjectContainer obj = new TestObjectContainer();
+        obj.foo = Lists.newArrayList("a", "b", "c");
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        List<String> list = mutObj.getField("foo");
+
+        list.add("!"); // "a", "b", "c", "!"
+        list.add(0, "_"); // "_", "a", "b", "c", "!"
+
+        String s = list.remove(1); // "_", "b", "c", "!"
+        assertEquals("a", s);
+
+        assertEquals(Arrays.asList("c", "!"), list.subList(2, 4));
+        assertEquals(1, list.indexOf("b"));
+        assertEquals(1, list.lastIndexOf("b"));
+
+        TestObjectContainer res = mutObj.build().deserialize();
+
+        assertTrue(res.foo instanceof ArrayList);
+        assertEquals(Arrays.asList("_", "b", "c", "!"), res.foo);
+    }
+
+    /**
+     *
+     */
+    public void testArrayListClear() {
+        TestObjectContainer obj = new TestObjectContainer();
+        obj.foo = Lists.newArrayList("a", "b", "c");
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        List<String> list = mutObj.getField("foo");
+
+        list.clear();
+
+        assertEquals(Collections.emptyList(), mutObj.build().<TestObjectContainer>deserialize().foo);
+    }
+
+    /**
+     *
+     */
+    public void testArrayListWriteUnmodifiable() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        ArrayList<Object> src = Lists.newArrayList(obj, "a", "b", "c");
+
+        obj.foo = src;
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        TestObjectContainer deserialized = mutObj.build().deserialize();
+
+        List<Object> res = (List<Object>)deserialized.foo;
+
+        src.set(0, deserialized);
+
+        assertEquals(src, res);
+    }
+
+    /**
+     *
+     */
+    public void testLinkedListRead() {
+        TestObjectContainer obj = new TestObjectContainer();
+        obj.foo = Lists.newLinkedList(Arrays.asList(obj, "a"));
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        List<Object> list = mutObj.getField("foo");
+
+        assert list.equals(Lists.newLinkedList(Arrays.asList(mutObj, "a")));
+    }
+
+    /**
+     *
+     */
+    public void testLinkedListOverride() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        List<Object> list = Lists.newLinkedList(Arrays.asList(mutObj, "a", Lists.newLinkedList(Arrays.asList(1, 2))));
+
+        mutObj.setField("foo", list);
+
+        TestObjectContainer res = mutObj.build().deserialize();
+
+        list.set(0, res);
+
+        assertNotSame(list, res.foo);
+        assertEquals(list, res.foo);
+    }
+
+    /**
+     *
+     */
+    public void testLinkedListModification() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        obj.foo = Lists.newLinkedList(Arrays.asList("a", "b", "c"));
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        List<String> list = mutObj.getField("foo");
+
+        list.add("!"); // "a", "b", "c", "!"
+        list.add(0, "_"); // "_", "a", "b", "c", "!"
+
+        String s = list.remove(1); // "_", "b", "c", "!"
+        assertEquals("a", s);
+
+        assertEquals(Arrays.asList("c", "!"), list.subList(2, 4));
+        assertEquals(1, list.indexOf("b"));
+        assertEquals(1, list.lastIndexOf("b"));
+
+        TestObjectContainer res = mutObj.build().deserialize();
+
+        assertTrue(res.foo instanceof LinkedList);
+        assertEquals(Arrays.asList("_", "b", "c", "!"), res.foo);
+    }
+
+    /**
+     *
+     */
+    public void testLinkedListWriteUnmodifiable() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        LinkedList<Object> src = Lists.newLinkedList(Arrays.asList(obj, "a", "b", "c"));
+
+        obj.foo = src;
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        TestObjectContainer deserialized = mutObj.build().deserialize();
+
+        List<Object> res = (List<Object>)deserialized.foo;
+
+        src.set(0, deserialized);
+
+        assertEquals(src, res);
+    }
+
+    /**
+     *
+     */
+    public void testHashSetRead() {
+        TestObjectContainer obj = new TestObjectContainer();
+        obj.foo = Sets.newHashSet(obj, "a");
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        Set<Object> set = mutObj.getField("foo");
+
+        assert set.equals(Sets.newHashSet(mutObj, "a"));
+    }
+
+    /**
+     *
+     */
+    public void testHashSetOverride() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        Set<Object> c = Sets.newHashSet(mutObj, "a", Sets.newHashSet(1, 2));
+
+        mutObj.setField("foo", c);
+
+        TestObjectContainer res = mutObj.build().deserialize();
+
+        c.remove(mutObj);
+        c.add(res);
+
+        assertNotSame(c, res.foo);
+        assertEquals(c, res.foo);
+    }
+
+    /**
+     *
+     */
+    public void testHashSetModification() {
+        TestObjectContainer obj = new TestObjectContainer();
+        obj.foo = Sets.newHashSet("a", "b", "c");
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        Set<String> set = mutObj.getField("foo");
+
+        set.remove("b");
+        set.add("!");
+
+        assertEquals(Sets.newHashSet("a", "!", "c"), set);
+        assertTrue(set.contains("a"));
+        assertTrue(set.contains("!"));
+
+        TestObjectContainer res = mutObj.build().deserialize();
+
+        assertTrue(res.foo instanceof HashSet);
+        assertEquals(Sets.newHashSet("a", "!", "c"), res.foo);
+    }
+
+    /**
+     *
+     */
+    public void testHashSetWriteUnmodifiable() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        Set<Object> src = Sets.newHashSet(obj, "a", "b", "c");
+
+        obj.foo = src;
+
+        TestObjectContainer deserialized = wrap(obj).build().deserialize();
+
+        Set<Object> res = (Set<Object>)deserialized.foo;
+
+        src.remove(obj);
+        src.add(deserialized);
+
+        assertEquals(src, res);
+    }
+
+    /**
+     *
+     */
+    public void testMapRead() {
+        TestObjectContainer obj = new TestObjectContainer();
+        obj.foo = Maps.newHashMap(ImmutableMap.of(obj, "a", "b", obj));
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        Map<Object, Object> map = mutObj.getField("foo");
+
+        assert map.equals(ImmutableMap.of(mutObj, "a", "b", mutObj));
+    }
+
+    /**
+     *
+     */
+    public void testMapOverride() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        Map<Object, Object> map = Maps.newHashMap(ImmutableMap.of(mutObj, "a", "b", mutObj));
+
+        mutObj.setField("foo", map);
+
+        TestObjectContainer res = mutObj.build().deserialize();
+
+        assertEquals(ImmutableMap.of(res, "a", "b", res), res.foo);
+    }
+
+    /**
+     *
+     */
+    public void testMapModification() {
+        TestObjectContainer obj = new TestObjectContainer();
+        obj.foo = Maps.newHashMap(ImmutableMap.of(1, "a", 2, "b"));
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        Map<Object, Object> map = mutObj.getField("foo");
+
+        map.put(3, mutObj);
+        Object rmv = map.remove(1);
+
+        assertEquals("a", rmv);
+
+        TestObjectContainer res = mutObj.build().deserialize();
+
+        assertEquals(ImmutableMap.of(2, "b", 3, res), res.foo);
+    }
+
+    /**
+     *
+     */
+    public void testEnumArrayModification() {
+        TestObjectAllTypes obj = new TestObjectAllTypes();
+
+        obj.enumArr = new TestObjectEnum[] {TestObjectEnum.A, TestObjectEnum.B};
+
+        IgniteObjectBuilderImpl mutObj = wrap(obj);
+
+        PortableBuilderEnum[] arr = mutObj.getField("enumArr");
+        arr[0] = new PortableBuilderEnum(mutObj.typeId(), TestObjectEnum.B);
+
+        TestObjectAllTypes res = mutObj.build().deserialize();
+
+        Assert.assertArrayEquals(new TestObjectEnum[] {TestObjectEnum.A, TestObjectEnum.B}, res.enumArr);
+    }
+
+    /**
+     *
+     */
+    public void testEditObjectWithRawData() {
+        GridIgniteObjectMarshalerAwareTestClass obj = new GridIgniteObjectMarshalerAwareTestClass();
+
+        obj.s = "a";
+        obj.sRaw = "aa";
+
+        IgniteObjectBuilderImpl mutableObj = wrap(obj);
+
+        mutableObj.setField("s", "z");
+
+        GridIgniteObjectMarshalerAwareTestClass res = mutableObj.build().deserialize();
+        assertEquals("z", res.s);
+        assertEquals("aa", res.sRaw);
+    }
+
+    /**
+     *
+     */
+    public void testHashCode() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        IgniteObjectBuilderImpl mutableObj = wrap(obj);
+
+        assertEquals(obj.hashCode(), mutableObj.build().hashCode());
+
+        mutableObj.hashCode(25);
+
+        assertEquals(25, mutableObj.build().hashCode());
+    }
+
+    /**
+     *
+     */
+    public void testCollectionsInCollection() {
+        TestObjectContainer obj = new TestObjectContainer();
+        obj.foo = Lists.newArrayList(
+            Lists.newArrayList(1, 2),
+            Lists.newLinkedList(Arrays.asList(1, 2)),
+            Sets.newHashSet("a", "b"),
+            Sets.newLinkedHashSet(Arrays.asList("a", "b")),
+            Maps.newHashMap(ImmutableMap.of(1, "a", 2, "b")));
+
+        TestObjectContainer deserialized = wrap(obj).build().deserialize();
+
+        assertEquals(obj.foo, deserialized.foo);
+    }
+
+    /**
+     *
+     */
+    public void testMapEntryModification() {
+        TestObjectContainer obj = new TestObjectContainer();
+        obj.foo = ImmutableMap.of(1, "a").entrySet().iterator().next();
+
+        IgniteObjectBuilderImpl mutableObj = wrap(obj);
+
+        Map.Entry<Object, Object> entry = mutableObj.getField("foo");
+
+        assertEquals(1, entry.getKey());
+        assertEquals("a", entry.getValue());
+
+        entry.setValue("b");
+
+        TestObjectContainer res = mutableObj.build().deserialize();
+
+        assertEquals(new GridMapEntry<>(1, "b"), res.foo);
+    }
+
+    /**
+     *
+     */
+    public void testMapEntryOverride() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        IgniteObjectBuilderImpl mutableObj = wrap(obj);
+
+        mutableObj.setField("foo", new GridMapEntry<>(1, "a"));
+
+        TestObjectContainer res = mutableObj.build().deserialize();
+
+        assertEquals(new GridMapEntry<>(1, "a"), res.foo);
+    }
+
+    /**
+     *
+     */
+    public void testMetadataChangingDoublePut() {
+        IgniteObjectBuilderImpl mutableObj = wrap(new TestObjectContainer());
+
+        mutableObj.setField("xx567", "a");
+        mutableObj.setField("xx567", "b");
+
+        mutableObj.build();
+
+        IgniteObjectMetadata metadata = portables().metadata(TestObjectContainer.class);
+
+        assertEquals("String", metadata.fieldTypeName("xx567"));
+    }
+
+    /**
+     *
+     */
+    public void testMetadataChangingDoublePut2() {
+        IgniteObjectBuilderImpl mutableObj = wrap(new TestObjectContainer());
+
+        mutableObj.setField("xx567", "a");
+        mutableObj.setField("xx567", "b");
+
+        mutableObj.build();
+
+        IgniteObjectMetadata metadata = portables().metadata(TestObjectContainer.class);
+
+        assertEquals("String", metadata.fieldTypeName("xx567"));
+    }
+
+    /**
+     *
+     */
+    public void testMetadataChanging() {
+        TestObjectContainer c = new TestObjectContainer();
+
+        IgniteObjectBuilderImpl mutableObj = wrap(c);
+
+        mutableObj.setField("intField", 1);
+        mutableObj.setField("intArrField", new int[] {1});
+        mutableObj.setField("arrField", new String[] {"1"});
+        mutableObj.setField("strField", "1");
+        mutableObj.setField("colField", Lists.newArrayList("1"));
+        mutableObj.setField("mapField", Maps.newHashMap(ImmutableMap.of(1, "1")));
+        mutableObj.setField("enumField", TestObjectEnum.A);
+        mutableObj.setField("enumArrField", new Enum[] {TestObjectEnum.A});
+
+        mutableObj.build();
+
+        IgniteObjectMetadata metadata = portables().metadata(c.getClass());
+
+        assertTrue(metadata.fields().containsAll(Arrays.asList("intField", "intArrField", "arrField", "strField",
+            "colField", "mapField", "enumField", "enumArrField")));
+
+        assertEquals("int", metadata.fieldTypeName("intField"));
+        assertEquals("int[]", metadata.fieldTypeName("intArrField"));
+        assertEquals("String[]", metadata.fieldTypeName("arrField"));
+        assertEquals("String", metadata.fieldTypeName("strField"));
+        assertEquals("Collection", metadata.fieldTypeName("colField"));
+        assertEquals("Map", metadata.fieldTypeName("mapField"));
+        assertEquals("Enum", metadata.fieldTypeName("enumField"));
+        assertEquals("Enum[]", metadata.fieldTypeName("enumArrField"));
+    }
+
+    /**
+     *
+     */
+    public void testDateInObjectField() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        obj.foo = new Date();
+
+        IgniteObjectBuilderImpl mutableObj = wrap(obj);
+
+        assertEquals(Date.class, mutableObj.getField("foo").getClass());
+    }
+
+    /**
+     *
+     */
+    public void testTimestampInObjectField() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        obj.foo = new Timestamp(100020003);
+
+        IgniteObjectBuilderImpl mutableObj = wrap(obj);
+
+        assertEquals(Timestamp.class, mutableObj.getField("foo").getClass());
+    }
+
+    /**
+     *
+     */
+    public void testDateInCollection() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        obj.foo = Lists.newArrayList(new Date());
+
+        IgniteObjectBuilderImpl mutableObj = wrap(obj);
+
+        assertEquals(Date.class, ((List<?>)mutableObj.getField("foo")).get(0).getClass());
+    }
+
+    /**
+     *
+     */
+    public void testTimestampInCollection() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        obj.foo = Lists.newArrayList(new Timestamp(100020003));
+
+        IgniteObjectBuilderImpl mutableObj = wrap(obj);
+
+        assertEquals(Timestamp.class, ((List<?>)mutableObj.getField("foo")).get(0).getClass());
+    }
+
+    /**
+     *
+     */
+    @SuppressWarnings("AssertEqualsBetweenInconvertibleTypes")
+    public void testDateArrayOverride() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        IgniteObjectBuilderImpl mutableObj = wrap(obj);
+
+        Date[] arr = { new Date() };
+
+        mutableObj.setField("foo", arr);
+
+        TestObjectContainer res = mutableObj.build().deserialize();
+
+        assertEquals(Date[].class, res.foo.getClass());
+        assertTrue(Objects.deepEquals(arr, res.foo));
+    }
+
+    /**
+     *
+     */
+    @SuppressWarnings("AssertEqualsBetweenInconvertibleTypes")
+    public void testTimestampArrayOverride() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        IgniteObjectBuilderImpl mutableObj = wrap(obj);
+
+        Timestamp[] arr = { new Timestamp(100020003) };
+
+        mutableObj.setField("foo", arr);
+
+        TestObjectContainer res = mutableObj.build().deserialize();
+
+        assertEquals(Timestamp[].class, res.foo.getClass());
+        assertTrue(Objects.deepEquals(arr, res.foo));
+    }
+
+    /**
+     *
+     */
+    public void testChangeMap() {
+        AddressBook addrBook = new AddressBook();
+
+        addrBook.addCompany(new Company(1, "Google inc", 100, new Address("Saint-Petersburg", "Torzhkovskya", 1, 53), "occupation"));
+        addrBook.addCompany(new Company(2, "Apple inc", 100, new Address("Saint-Petersburg", "Torzhkovskya", 1, 54), "occupation"));
+        addrBook.addCompany(new Company(3, "Microsoft", 100, new Address("Saint-Petersburg", "Torzhkovskya", 1, 55), "occupation"));
+        addrBook.addCompany(new Company(4, "Oracle", 100, new Address("Saint-Petersburg", "Nevskiy", 1, 1), "occupation"));
+
+        IgniteObjectBuilderImpl mutableObj = wrap(addrBook);
+
+        Map<String, List<IgniteObjectBuilderImpl>> map = mutableObj.getField("companyByStreet");
+
+        List<IgniteObjectBuilderImpl> list = map.get("Torzhkovskya");
+
+        IgniteObjectBuilderImpl company = list.get(0);
+
+        assert "Google inc".equals(company.<String>getField("name"));
+
+        list.remove(0);
+
+        AddressBook res = mutableObj.build().deserialize();
+
+        assertEquals(Arrays.asList("Nevskiy", "Torzhkovskya"), new ArrayList<>(res.getCompanyByStreet().keySet()));
+
+        List<Company> torzhkovskyaCompanies = res.getCompanyByStreet().get("Torzhkovskya");
+
+        assertEquals(2, torzhkovskyaCompanies.size());
+        assertEquals("Apple inc", torzhkovskyaCompanies.get(0).name);
+    }
+
+    /**
+     *
+     */
+    public void testSavingObjectWithNotZeroStart() {
+        TestObjectOuter out = new TestObjectOuter();
+        TestObjectInner inner = new TestObjectInner();
+
+        out.inner = inner;
+        inner.outer = out;
+
+        IgniteObjectBuilderImpl builder = wrap(out);
+
+        IgniteObjectBuilderImpl innerBuilder = builder.getField("inner");
+
+        TestObjectInner res = innerBuilder.build().deserialize();
+
+        assertSame(res, res.outer.inner);
+    }
+
+    /**
+     *
+     */
+    public void testPortableObjectField() {
+        TestObjectContainer container = new TestObjectContainer(toPortable(new TestObjectArrayList()));
+
+        IgniteObjectBuilderImpl wrapper = wrap(container);
+
+        assertTrue(wrapper.getField("foo") instanceof IgniteObject);
+
+        TestObjectContainer deserialized = wrapper.build().deserialize();
+        assertTrue(deserialized.foo instanceof IgniteObject);
+    }
+
+    /**
+     *
+     */
+    public void testAssignPortableObject() {
+        TestObjectContainer container = new TestObjectContainer();
+
+        IgniteObjectBuilderImpl wrapper = wrap(container);
+
+        wrapper.setField("foo", toPortable(new TestObjectArrayList()));
+
+        TestObjectContainer deserialized = wrapper.build().deserialize();
+        assertTrue(deserialized.foo instanceof TestObjectArrayList);
+    }
+
+    /**
+     *
+     */
+    public void testRemoveFromNewObject() {
+        IgniteObjectBuilderImpl wrapper = newWrapper(TestObjectAllTypes.class);
+
+        wrapper.setField("str", "a");
+
+        wrapper.removeField("str");
+
+        assertNull(wrapper.build().<TestObjectAllTypes>deserialize().str);
+    }
+
+    /**
+     *
+     */
+    public void testRemoveFromExistingObject() {
+        TestObjectAllTypes obj = new TestObjectAllTypes();
+        obj.setDefaultData();
+
+        IgniteObjectBuilderImpl wrapper = wrap(toPortable(obj));
+
+        wrapper.removeField("str");
+
+        assertNull(wrapper.build().<TestObjectAllTypes>deserialize().str);
+    }
+
+    /**
+     *
+     */
+    public void testCyclicArrays() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        Object[] arr1 = new Object[1];
+        Object[] arr2 = new Object[] {arr1};
+
+        arr1[0] = arr2;
+
+        obj.foo = arr1;
+
+        TestObjectContainer res = toPortable(obj).deserialize();
+
+        Object[] resArr = (Object[])res.foo;
+
+        assertSame(((Object[])resArr[0])[0], resArr);
+    }
+
+    /**
+     *
+     */
+    @SuppressWarnings("TypeMayBeWeakened")
+    public void testCyclicArrayList() {
+        TestObjectContainer obj = new TestObjectContainer();
+
+        List<Object> arr1 = new ArrayList<>();
+        List<Object> arr2 = new ArrayList<>();
+
+        arr1.add(arr2);
+        arr2.add(arr1);
+
+        obj.foo = arr1;
+
+        TestObjectContainer res = toPortable(obj).deserialize();
+
+        List<?> resArr = (List<?>)res.foo;
+
+        assertSame(((List<Object>)resArr.get(0)).get(0), resArr);
+    }
+
+    /**
+     * @param obj Object.
+     * @return Object in portable format.
+     */
+    private IgniteObject toPortable(Object obj) {
+        return portables().toPortable(obj);
+    }
+
+    /**
+     * @param obj Object.
+     * @return GridMutablePortableObject.
+     */
+    private IgniteObjectBuilderImpl wrap(Object obj) {
+        return IgniteObjectBuilderImpl.wrap(toPortable(obj));
+    }
+
+    /**
+     * @param aCls Class.
+     * @return Wrapper.
+     */
+    private IgniteObjectBuilderImpl newWrapper(Class<?> aCls) {
+        CacheObjectPortableProcessorImpl processor = (CacheObjectPortableProcessorImpl)(
+            (IgniteObjectsImpl)portables()).processor();
+
+        return new IgniteObjectBuilderImpl(processor.portableContext(), processor.typeId(aCls.getName()),
+            aCls.getSimpleName());
+    }
+}
\ No newline at end of file