You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2017/05/26 11:07:19 UTC

[2/2] ignite git commit: IGNITE-4575: Improved binary enums support. This closes #1968.

IGNITE-4575: Improved binary enums support. This closes #1968.


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

Branch: refs/heads/master
Commit: b5c7b6f5ed81a9cee242e3abb052c29ec571a9a9
Parents: d38ca8b
Author: Sergey Kalashnikov <sk...@gridgain.com>
Authored: Fri May 26 14:07:06 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri May 26 14:07:06 2017 +0300

----------------------------------------------------------------------
 .../java/org/apache/ignite/IgniteBinary.java    |  23 ++-
 .../org/apache/ignite/binary/BinaryObject.java  |   8 +
 .../org/apache/ignite/binary/BinaryType.java    |   5 +
 .../ignite/binary/BinaryTypeConfiguration.java  |  26 +++
 .../binary/BinaryCachingMetadataHandler.java    |   5 +
 .../internal/binary/BinaryClassDescriptor.java  |   4 +-
 .../ignite/internal/binary/BinaryContext.java   |  60 +++++--
 .../internal/binary/BinaryEnumObjectImpl.java   |  30 +++-
 .../internal/binary/BinaryFieldAccessor.java    |  10 ++
 .../ignite/internal/binary/BinaryMetadata.java  |  93 +++++++++-
 .../internal/binary/BinaryMetadataHandler.java  |   9 +
 .../binary/BinaryNoopMetadataHandler.java       |   5 +
 .../internal/binary/BinaryObjectExImpl.java     |   5 +
 .../internal/binary/BinaryReaderExImpl.java     |  18 ++
 .../ignite/internal/binary/BinaryTypeImpl.java  |  15 ++
 .../ignite/internal/binary/BinaryTypeProxy.java |   6 +
 .../ignite/internal/binary/BinaryUtils.java     | 104 ++++++++++-
 .../internal/binary/BinaryWriterExImpl.java     |  18 +-
 .../internal/binary/GridBinaryMarshaller.java   |   3 +
 .../binary/builder/BinaryBuilderSerializer.java |  10 +-
 .../binary/builder/BinaryObjectBuilderImpl.java |   2 +-
 .../binary/CacheObjectBinaryProcessor.java      |  21 ++-
 .../binary/CacheObjectBinaryProcessorImpl.java  |  72 +++++++-
 .../cache/binary/IgniteBinaryImpl.java          |  26 +++
 .../processors/cacheobject/NoOpBinary.java      |  12 ++
 .../platform/PlatformContextImpl.java           |  29 ++-
 .../binary/PlatformBinaryProcessor.java         |  25 +++
 .../internal/binary/BinaryEnumsSelfTest.java    | 146 ++++++++++++++-
 .../binary/TestCachingMetadataHandler.java      |   5 +
 .../platform/PlatformComputeEchoTask.java       |  13 ++
 .../Binary/BinaryBuilderSelfTest.cs             |  88 +++++++--
 .../Compute/ComputeApiTest.cs                   |  25 +++
 .../Binary/BinaryTypeConfiguration.cs           |   3 +-
 .../dotnet/Apache.Ignite.Core/Binary/IBinary.cs |  24 +++
 .../Apache.Ignite.Core/Binary/IBinaryObject.cs  |   8 +
 .../Apache.Ignite.Core/Binary/IBinaryType.cs    |   6 +
 .../Apache.Ignite.Core/Impl/Binary/Binary.cs    |  67 ++++++-
 .../Impl/Binary/BinaryEnum.cs                   |  11 +-
 .../Impl/Binary/BinaryObject.cs                 |  13 +-
 .../Impl/Binary/BinaryProcessor.cs              |  65 ++++++-
 .../Impl/Binary/BinaryReader.cs                 |  10 +-
 .../Impl/Binary/BinarySystemHandlers.cs         |  25 +--
 .../Impl/Binary/BinaryUtils.cs                  |  19 ++
 .../Impl/Binary/BinaryWriter.cs                 |   4 +-
 .../Impl/Binary/Marshaller.cs                   |  88 ++++-----
 .../Impl/Binary/Metadata/BinaryType.cs          | 179 ++++++++++++++++++-
 .../Impl/Binary/Metadata/BinaryTypeHolder.cs    |  44 +++--
 47 files changed, 1338 insertions(+), 149 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/IgniteBinary.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteBinary.java b/modules/core/src/main/java/org/apache/ignite/IgniteBinary.java
index 1d1c0c3..3550ff5 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteBinary.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteBinary.java
@@ -23,6 +23,7 @@ import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.LinkedList;
+import java.util.Map;
 import java.util.TreeMap;
 import java.util.UUID;
 import org.apache.ignite.binary.BinaryObjectBuilder;
@@ -374,11 +375,29 @@ public interface IgniteBinary {
     public Collection<BinaryType> types() throws BinaryObjectException;
 
     /**
-     * Create enum object.
+     * Create enum object using value.
      *
      * @param typeName Type name.
      * @param ord Ordinal.
      * @return Enum object.
      */
-    public BinaryObject buildEnum(String typeName, int ord);
+    public BinaryObject buildEnum(String typeName, int ord) throws BinaryObjectException;
+
+    /**
+     * Create enum object using name.
+     *
+     * @param typeName Type name.
+     * @param name Name.
+     * @return Enum object.
+     */
+    public BinaryObject buildEnum(String typeName, String name) throws BinaryObjectException;
+
+    /**
+     * Register enum type.
+     *
+     * @param typeName Type name.
+     * @param vals Mapping of enum constant names to ordinals.
+     * @return Binary type for registered enum.
+     */
+    public BinaryType registerEnum(String typeName, Map<String, Integer> vals) throws BinaryObjectException;
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/binary/BinaryObject.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/binary/BinaryObject.java b/modules/core/src/main/java/org/apache/ignite/binary/BinaryObject.java
index 3d99757..b9e653f 100644
--- a/modules/core/src/main/java/org/apache/ignite/binary/BinaryObject.java
+++ b/modules/core/src/main/java/org/apache/ignite/binary/BinaryObject.java
@@ -162,4 +162,12 @@ public interface BinaryObject extends Serializable, Cloneable {
      * @throws BinaryObjectException If object is not enum.
      */
     public int enumOrdinal() throws BinaryObjectException;
+
+    /**
+     * Get name for this enum object. Use {@link BinaryType#isEnum()} to check if object is of enum type.
+     *
+     * @return Name.
+     * @throws BinaryObjectException If object is not enum.
+     */
+    public String enumName() throws BinaryObjectException;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/binary/BinaryType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/binary/BinaryType.java b/modules/core/src/main/java/org/apache/ignite/binary/BinaryType.java
index f184a8c..f4bc206 100644
--- a/modules/core/src/main/java/org/apache/ignite/binary/BinaryType.java
+++ b/modules/core/src/main/java/org/apache/ignite/binary/BinaryType.java
@@ -79,4 +79,9 @@ public interface BinaryType {
      * @return {@code True} if type is enum.
      */
     public boolean isEnum();
+
+    /**
+     * @return Collection of enum values.
+     */
+    public Collection<BinaryObject> enumValues();
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/binary/BinaryTypeConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/binary/BinaryTypeConfiguration.java b/modules/core/src/main/java/org/apache/ignite/binary/BinaryTypeConfiguration.java
index 54b853c..2d00bd2 100644
--- a/modules/core/src/main/java/org/apache/ignite/binary/BinaryTypeConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/binary/BinaryTypeConfiguration.java
@@ -23,6 +23,9 @@ import org.apache.ignite.internal.util.typedef.internal.A;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.LinkedHashMap;
+import java.util.Map;
+
 /**
  * Defines configuration properties for a specific binary type. Providing per-type
  * configuration is optional, as it is generally enough, and also optional, to provide global binary
@@ -46,6 +49,9 @@ public class BinaryTypeConfiguration {
     /** Enum flag. */
     private boolean isEnum;
 
+    /** Enum names to ordinals mapping. */
+    private Map<String, Integer> enumValues;
+
     /**
      * Constructor.
      */
@@ -64,6 +70,7 @@ public class BinaryTypeConfiguration {
         idMapper = other.idMapper;
         isEnum = other.isEnum;
         serializer = other.serializer;
+        enumValues = other.enumValues != null ? new LinkedHashMap<>(other.enumValues) : null;
         typeName = other.typeName;
     }
 
@@ -179,6 +186,25 @@ public class BinaryTypeConfiguration {
         return this;
     }
 
+    /**
+     * Set enum ordinal to names mapping.
+     *
+     * @param values Map of enum name to ordinal.
+     * @return {@code this} for chaining.
+     */
+    public BinaryTypeConfiguration setEnumValues(@Nullable Map<String, Integer> values) {
+        this.enumValues = values;
+
+        return this;
+    }
+
+    /**
+     * @return Enum name to ordinal mapping
+     */
+    @Nullable public Map<String, Integer> getEnumValues() {
+        return enumValues;
+    }
+
     /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(BinaryTypeConfiguration.class, this, super.toString());

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryCachingMetadataHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryCachingMetadataHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryCachingMetadataHandler.java
index 24a393d..27cccaa 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryCachingMetadataHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryCachingMetadataHandler.java
@@ -69,6 +69,11 @@ public class BinaryCachingMetadataHandler implements BinaryMetadataHandler {
     }
 
     /** {@inheritDoc} */
+    @Override public synchronized BinaryMetadata metadata0(int typeId) throws BinaryObjectException {
+        return ((BinaryTypeImpl)metas.get(typeId)).metadata();
+    }
+
+    /** {@inheritDoc} */
     @Override public synchronized BinaryType metadata(int typeId, int schemaId) throws BinaryObjectException {
         BinaryTypeImpl type = (BinaryTypeImpl) metas.get(typeId);
         return type.metadata().hasSchema(schemaId) ? type : null;

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java
index 7194f49..adfdcfc 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java
@@ -758,7 +758,7 @@ public class BinaryClassDescriptor {
                                 BinarySchema newSchema = collector.schema();
 
                                 BinaryMetadata meta = new BinaryMetadata(typeId, typeName, collector.meta(),
-                                    affKeyFieldName, Collections.singleton(newSchema), false);
+                                    affKeyFieldName, Collections.singleton(newSchema), false, null);
 
                                 ctx.updateMetadata(typeId, meta);
 
@@ -779,7 +779,7 @@ public class BinaryClassDescriptor {
                 if (userType && !stableSchemaPublished) {
                     // Update meta before write object with new schema
                     BinaryMetadata meta = new BinaryMetadata(typeId, typeName, stableFieldsMeta,
-                        affKeyFieldName, Collections.singleton(stableSchema), false);
+                        affKeyFieldName, Collections.singleton(stableSchema), false, null);
 
                     ctx.updateMetadata(typeId, meta);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
index da46496..70bc2f9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
@@ -461,17 +461,17 @@ public class BinaryContext {
 
                     for (String clsName0 : classesInPackage(pkgName))
                         descs.add(clsName0, mapper, serializer, identity, affFields.get(clsName0),
-                            typeCfg.isEnum(), true);
+                            typeCfg.isEnum(), typeCfg.getEnumValues(), true);
                 }
                 else
                     descs.add(clsName, mapper, serializer, identity, affFields.get(clsName),
-                        typeCfg.isEnum(), false);
+                        typeCfg.isEnum(), typeCfg.getEnumValues(), false);
             }
         }
 
         for (TypeDescriptor desc : descs.descriptors())
             registerUserType(desc.clsName, desc.mapper, desc.serializer, desc.identity, desc.affKeyFieldName,
-                desc.isEnum);
+                desc.isEnum, desc.enumMap);
 
         BinaryInternalMapper globalMapper = resolveMapper(globalNameMapper, globalIdMapper);
 
@@ -649,7 +649,8 @@ public class BinaryContext {
                         desc0.typeName(),
                         desc0.fieldsMeta(),
                         desc0.affFieldKeyName(),
-                        schemas, desc0.isEnum());
+                        schemas, desc0.isEnum(),
+                        cls.isEnum() ? enumMap(cls) : null);
 
                     metaHnd.addMeta(desc0.typeId(), meta.wrap(this));
 
@@ -799,8 +800,8 @@ public class BinaryContext {
         );
 
         if (!deserialize)
-            metaHnd.addMeta(typeId,
-                new BinaryMetadata(typeId, typeName, desc.fieldsMeta(), affFieldName, null, desc.isEnum()).wrap(this));
+            metaHnd.addMeta(typeId, new BinaryMetadata(typeId, typeName, desc.fieldsMeta(), affFieldName, null,
+                desc.isEnum(), cls.isEnum() ? enumMap(cls) : null).wrap(this));
 
         descByCls.put(cls, desc);
 
@@ -1095,6 +1096,7 @@ public class BinaryContext {
      * @param identity Type identity.
      * @param affKeyFieldName Affinity key field name.
      * @param isEnum If enum.
+     * @param enumMap Enum name to ordinal mapping.
      * @throws BinaryObjectException In case of error.
      */
     @SuppressWarnings("ErrorNotRethrown")
@@ -1103,8 +1105,8 @@ public class BinaryContext {
         @Nullable BinarySerializer serializer,
         @Nullable BinaryIdentityResolver identity,
         @Nullable String affKeyFieldName,
-        boolean isEnum)
-        throws BinaryObjectException {
+        boolean isEnum,
+        @Nullable Map<String, Integer> enumMap) throws BinaryObjectException {
         assert mapper != null;
 
         Class<?> cls = null;
@@ -1172,7 +1174,8 @@ public class BinaryContext {
             predefinedTypes.put(id, desc);
         }
 
-        metaHnd.addMeta(id, new BinaryMetadata(id, typeName, fieldsMeta, affKeyFieldName, null, isEnum).wrap(this));
+        metaHnd.addMeta(id,
+            new BinaryMetadata(id, typeName, fieldsMeta, affKeyFieldName, null, isEnum, enumMap).wrap(this));
     }
 
     /**
@@ -1222,6 +1225,16 @@ public class BinaryContext {
     }
 
     /**
+     *
+     * @param typeId Type ID
+     * @return Meta data.
+     * @throws BinaryObjectException In case of error.
+     */
+    @Nullable public BinaryMetadata metadata0(int typeId) throws BinaryObjectException {
+        return metaHnd != null ? metaHnd.metadata0(typeId) : null;
+    }
+
+    /**
      * @param typeId Type ID.
      * @param schemaId Schema ID.
      * @return Meta data.
@@ -1351,6 +1364,24 @@ public class BinaryContext {
     }
 
     /**
+     *
+     * @param cls Class
+     * @return Enum name to ordinal mapping.
+     */
+    private static Map<String, Integer> enumMap(Class<?> cls) {
+        assert cls.isEnum();
+
+        Object[] enumVals = cls.getEnumConstants();
+
+        Map<String, Integer> enumMap = new LinkedHashMap<>(enumVals.length);
+
+        for (Object enumVal : enumVals)
+            enumMap.put(((Enum)enumVal).name(), ((Enum)enumVal).ordinal());
+
+        return enumMap;
+    }
+
+    /**
      * Type descriptors.
      */
     private static class TypeDescriptors {
@@ -1366,6 +1397,7 @@ public class BinaryContext {
          * @param identity Key hashing mode.
          * @param affKeyFieldName Affinity key field name.
          * @param isEnum Enum flag.
+         * @param enumMap Enum constants mapping.
          * @param canOverride Whether this descriptor can be override.
          * @throws BinaryObjectException If failed.
          */
@@ -1375,6 +1407,7 @@ public class BinaryContext {
             BinaryIdentityResolver identity,
             String affKeyFieldName,
             boolean isEnum,
+            Map<String, Integer> enumMap,
             boolean canOverride)
             throws BinaryObjectException {
             TypeDescriptor desc = new TypeDescriptor(clsName,
@@ -1383,6 +1416,7 @@ public class BinaryContext {
                 identity,
                 affKeyFieldName,
                 isEnum,
+                enumMap,
                 canOverride);
 
             TypeDescriptor oldDesc = descs.get(clsName);
@@ -1425,6 +1459,9 @@ public class BinaryContext {
         /** Enum flag. */
         private boolean isEnum;
 
+        /** Enum ordinal to name mapping. */
+        private Map<String, Integer> enumMap;
+
         /** Whether this descriptor can be override. */
         private boolean canOverride;
 
@@ -1436,17 +1473,19 @@ public class BinaryContext {
          * @param identity Key hashing mode.
          * @param affKeyFieldName Affinity key field name.
          * @param isEnum Enum type.
+         * @param enumMap Mapping of enum names to ordinals.
          * @param canOverride Whether this descriptor can be override.
          */
         private TypeDescriptor(String clsName, BinaryInternalMapper mapper,
             BinarySerializer serializer, BinaryIdentityResolver identity, String affKeyFieldName, boolean isEnum,
-            boolean canOverride) {
+            Map<String, Integer> enumMap, boolean canOverride) {
             this.clsName = clsName;
             this.mapper = mapper;
             this.serializer = serializer;
             this.identity = identity;
             this.affKeyFieldName = affKeyFieldName;
             this.isEnum = isEnum;
+            this.enumMap = enumMap;
             this.canOverride = canOverride;
         }
 
@@ -1465,6 +1504,7 @@ public class BinaryContext {
                 identity = other.identity;
                 affKeyFieldName = other.affKeyFieldName;
                 isEnum = other.isEnum;
+                enumMap = other.enumMap;
                 canOverride = other.canOverride;
             }
             else if (!other.canOverride)

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java
index cc9941e..f889e45 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java
@@ -97,9 +97,18 @@ public class BinaryEnumObjectImpl implements BinaryObjectEx, Externalizable, Cac
     public BinaryEnumObjectImpl(BinaryContext ctx, byte[] arr) {
         assert ctx != null;
         assert arr != null;
-        assert arr[0] == GridBinaryMarshaller.ENUM;
 
-        valBytes = arr;
+        if (arr[0] == GridBinaryMarshaller.ENUM)
+            valBytes = arr;
+        else {
+            assert arr[0] == GridBinaryMarshaller.BINARY_ENUM;
+
+            valBytes = new byte[arr.length];
+
+            valBytes[0] = GridBinaryMarshaller.ENUM;
+
+            U.arrayCopy(arr, 1, valBytes, 1, arr.length - 1);
+        }
 
         this.ctx = ctx;
 
@@ -187,6 +196,23 @@ public class BinaryEnumObjectImpl implements BinaryObjectEx, Externalizable, Cac
     }
 
     /** {@inheritDoc} */
+    @Override public String enumName() throws BinaryObjectException {
+        BinaryMetadata metadata = ctx.metadata0(typeId);
+
+        if (metadata == null)
+            throw new BinaryObjectException("Failed to get metadata for enum [typeId=" +
+                typeId + ", typeName='" + clsName + "', ordinal=" + ord + "]");
+
+        String name = metadata.getEnumNameByOrdinal(ord);
+
+        if (name == null)
+            throw new BinaryObjectException("Unable to resolve enum constant name [typeId=" +
+                typeId + ", typeName='" + metadata.typeName() + "', ordinal=" + ord + "]");
+
+        return name;
+    }
+
+    /** {@inheritDoc} */
     @Override public int hashCode() {
         return 31 * typeId + ord;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java
index f7d35f0..567bee1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java
@@ -647,6 +647,11 @@ public abstract class BinaryFieldAccessor {
 
                     break;
 
+                case BINARY_ENUM:
+                    writer.doWriteBinaryEnum((BinaryEnumObjectImpl)val);
+
+                    break;
+
                 case ENUM_ARR:
                     writer.writeEnumArrayField((Object[])val);
 
@@ -863,6 +868,11 @@ public abstract class BinaryFieldAccessor {
 
                     break;
 
+                case BINARY_ENUM:
+                    val = reader.readBinaryEnum(id);
+
+                    break;
+
                 case BINARY:
                 case OBJECT:
                     val = reader.readObject(id);

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMetadata.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMetadata.java
index a8b7fcb..ead00b7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMetadata.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMetadata.java
@@ -27,9 +27,12 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
+
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.jetbrains.annotations.Nullable;
@@ -41,6 +44,9 @@ public class BinaryMetadata implements Externalizable {
     /** */
     private static final long serialVersionUID = 0L;
 
+    /** */
+    private static final int VERSION = 1;
+
     /** Type ID. */
     @GridToStringInclude(sensitive = true)
     private int typeId;
@@ -67,6 +73,12 @@ public class BinaryMetadata implements Externalizable {
     /** Whether this is enum type. */
     private boolean isEnum;
 
+    /** Enum name to ordinal mapping. */
+    private Map<String, Integer> nameToOrdinal;
+
+    /** Enum ordinal to name mapping. */
+    private Map<Integer, String> ordinalToName;
+
     /**
      * For {@link Externalizable}.
      */
@@ -83,9 +95,11 @@ public class BinaryMetadata implements Externalizable {
      * @param affKeyFieldName Affinity key field name.
      * @param schemas Schemas.
      * @param isEnum Enum flag.
+     * @param enumMap Enum name to ordinal mapping.
      */
     public BinaryMetadata(int typeId, String typeName, @Nullable Map<String, BinaryFieldMetadata> fields,
-        @Nullable String affKeyFieldName, @Nullable Collection<BinarySchema> schemas, boolean isEnum) {
+        @Nullable String affKeyFieldName, @Nullable Collection<BinarySchema> schemas, boolean isEnum,
+        @Nullable Map<String, Integer> enumMap) {
         assert typeName != null;
 
         this.typeId = typeId;
@@ -104,6 +118,15 @@ public class BinaryMetadata implements Externalizable {
             schemaIds = Collections.emptySet();
 
         this.isEnum = isEnum;
+
+        if (enumMap != null) {
+            this.nameToOrdinal = new LinkedHashMap<>(enumMap);
+
+            this.ordinalToName = new LinkedHashMap<>(enumMap.size());
+
+            for (Map.Entry<String, Integer> e: nameToOrdinal.entrySet())
+                this.ordinalToName.put(e.getValue(), e.getKey());
+        }
     }
 
     /**
@@ -197,6 +220,7 @@ public class BinaryMetadata implements Externalizable {
      * @exception IOException Includes any I/O exceptions that may occur.
      */
     public void writeTo(DataOutput out) throws IOException {
+        out.writeByte(VERSION);
         out.writeInt(typeId);
 
         U.writeString(out, typeName);
@@ -224,6 +248,18 @@ public class BinaryMetadata implements Externalizable {
         }
 
         out.writeBoolean(isEnum);
+
+        if (isEnum) {
+            Map<String, Integer> map = enumMap();
+
+            out.writeInt(map.size());
+
+            for (Map.Entry<String, Integer> e : map.entrySet()) {
+                U.writeString(out, e.getKey());
+
+                out.writeInt(e.getValue());
+            }
+        }
     }
 
     /** {@inheritDoc} */
@@ -242,6 +278,8 @@ public class BinaryMetadata implements Externalizable {
      * @exception IOException if I/O errors occur.
      */
     public void readFrom(DataInput in) throws IOException {
+        in.readByte(); //skip version
+
         typeId = in.readInt();
         typeName = U.readString(in);
 
@@ -285,6 +323,59 @@ public class BinaryMetadata implements Externalizable {
         }
 
         isEnum = in.readBoolean();
+
+        if (isEnum) {
+            int size = in.readInt();
+
+            if (size >= 0) {
+                ordinalToName = new LinkedHashMap<>(size);
+                nameToOrdinal = new LinkedHashMap<>(size);
+
+                for (int idx = 0; idx < size; idx++) {
+                    String name = U.readString(in);
+
+                    int ord = in.readInt();
+
+                    ordinalToName.put(ord, name);
+                    nameToOrdinal.put(name, ord);
+                }
+            }
+        }
+    }
+
+    /**
+     * Gets enum constant name given its ordinal value.
+     *
+     * @param ord Enum constant ordinal value.
+     * @return Enum constant name.
+     */
+    public String getEnumNameByOrdinal(int ord) {
+        if (ordinalToName == null)
+            return null;
+
+        return ordinalToName.get(ord);
+    }
+
+    /**
+     * Gets enum constant ordinal value given its name.
+     *
+     * @param name Enum constant name.
+     * @return Enum constant ordinal value.
+     */
+    public Integer getEnumOrdinalByName(String name) {
+        assert name != null;
+
+        return nameToOrdinal.get(name);
+    }
+
+    /**
+     * @return Name to ordinal mapping.
+     */
+    public Map<String, Integer> enumMap() {
+        if (nameToOrdinal == null)
+            return Collections.emptyMap();
+
+        return nameToOrdinal;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMetadataHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMetadataHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMetadataHandler.java
index 748a283..e565338 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMetadataHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMetadataHandler.java
@@ -43,6 +43,15 @@ public interface BinaryMetadataHandler {
     public BinaryType metadata(int typeId) throws BinaryObjectException;
 
     /**
+     * Gets unwrapped meta data for provided type ID.
+     *
+     * @param typeId Type ID.
+     * @return Metadata.
+     * @throws BinaryObjectException In case of error.
+     */
+    public BinaryMetadata metadata0(int typeId) throws BinaryObjectException;
+
+    /**
      * Gets metadata for provided type ID and schema ID.
      *
      * @param typeId Type ID.

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryNoopMetadataHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryNoopMetadataHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryNoopMetadataHandler.java
index 770d9c8..39c942a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryNoopMetadataHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryNoopMetadataHandler.java
@@ -52,6 +52,11 @@ public class BinaryNoopMetadataHandler implements BinaryMetadataHandler {
     }
 
     /** {@inheritDoc} */
+    @Override public BinaryMetadata metadata0(int typeId) throws BinaryObjectException {
+        return null;
+    }
+
+    /** {@inheritDoc} */
     @Override public BinaryType metadata(int typeId, int schemaId) throws BinaryObjectException {
         return null;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectExImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectExImpl.java
index ae9a160..b5e066b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectExImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectExImpl.java
@@ -77,6 +77,11 @@ public abstract class BinaryObjectExImpl implements BinaryObjectEx {
         throw new BinaryObjectException("Object is not enum.");
     }
 
+    /** {@inheritDoc} */
+    @Override public String enumName() throws BinaryObjectException {
+        throw new BinaryObjectException("Object is not enum.");
+    }
+
     /**
      * Get offset of data begin.
      *

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java
index c8ca803..2b7964c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java
@@ -41,6 +41,7 @@ import org.apache.ignite.internal.util.typedef.internal.SB;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import static org.apache.ignite.internal.binary.GridBinaryMarshaller.BINARY_ENUM;
 import static org.apache.ignite.internal.binary.GridBinaryMarshaller.BINARY_OBJ;
 import static org.apache.ignite.internal.binary.GridBinaryMarshaller.BOOLEAN;
 import static org.apache.ignite.internal.binary.GridBinaryMarshaller.BOOLEAN_ARR;
@@ -1426,6 +1427,15 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina
 
     /**
      * @param fieldId Field ID.
+     * @return Binary Enum
+     * @throws BinaryObjectException If failed.
+     */
+    @Nullable BinaryEnumObjectImpl readBinaryEnum(int fieldId) throws BinaryObjectException {
+        return findFieldById(fieldId) ? BinaryUtils.doReadBinaryEnum(in, ctx) : null;
+    }
+
+    /**
+     * @param fieldId Field ID.
      * @param cls Class.
      * @return Value.
      * @throws BinaryObjectException In case of error.
@@ -1930,6 +1940,14 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina
 
                 break;
 
+            case BINARY_ENUM:
+                obj = BinaryUtils.doReadBinaryEnum(in, ctx);
+
+                if (!GridBinaryMarshaller.KEEP_BINARIES.get())
+                    obj = ((BinaryObject)obj).deserialize();
+
+                break;
+
             case CLASS:
                 obj = BinaryUtils.doReadClass(in, ctx, ldr);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryTypeImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryTypeImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryTypeImpl.java
index 132702c..fac1ff9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryTypeImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryTypeImpl.java
@@ -17,9 +17,12 @@
 
 package org.apache.ignite.internal.binary;
 
+import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.binary.BinaryType;
 
+import java.util.ArrayList;
 import java.util.Collection;
+
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.typedef.internal.S;
 
@@ -80,6 +83,18 @@ public class BinaryTypeImpl implements BinaryType {
         return meta.isEnum();
     }
 
+    /** {@inheritDoc} */
+    @Override public Collection<BinaryObject> enumValues() {
+        Collection<Integer> ordinals = meta.enumMap().values();
+
+        ArrayList<BinaryObject> enumValues = new ArrayList<>(ordinals.size());
+
+        for (Integer ord: ordinals)
+            enumValues.add(new BinaryEnumObjectImpl(ctx, typeId(), typeName(), ord));
+
+        return enumValues;
+    }
+
     /**
      * @return Context.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryTypeProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryTypeProxy.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryTypeProxy.java
index df9901e..3a51050 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryTypeProxy.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryTypeProxy.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.binary;
 
 import org.apache.ignite.binary.BinaryField;
+import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.binary.BinaryObjectException;
 import org.apache.ignite.binary.BinaryType;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
@@ -92,6 +93,11 @@ public class BinaryTypeProxy implements BinaryType {
         return target().isEnum();
     }
 
+    /** {@inheritDoc} */
+    @Override public Collection<BinaryObject> enumValues() {
+        return target().enumValues();
+    }
+
     /**
      * @return Target type.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
index f36c137..00b15da 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
@@ -266,6 +266,7 @@ public class BinaryUtils {
         FIELD_TYPE_NAMES[GridBinaryMarshaller.TIME_ARR] = "Time[]";
         FIELD_TYPE_NAMES[GridBinaryMarshaller.OBJ_ARR] = "Object[]";
         FIELD_TYPE_NAMES[GridBinaryMarshaller.ENUM_ARR] = "Enum[]";
+        FIELD_TYPE_NAMES[GridBinaryMarshaller.BINARY_ENUM] = "Enum";
 
         if (wrapTrees()) {
             CLS_TO_WRITE_REPLACER.put(TreeMap.class, new BinaryTreeMapWriteReplacer());
@@ -975,6 +976,14 @@ public class BinaryUtils {
 
             boolean changed = false;
 
+            Map<String, Integer> mergedEnumMap = null;
+
+            if (!F.isEmpty(newMeta.enumMap())) {
+                mergedEnumMap = mergeEnumValues(oldMeta.typeName(), oldMeta.enumMap(), newMeta.enumMap());
+
+                changed = mergedEnumMap.size() > oldMeta.enumMap().size();
+            }
+
             for (Map.Entry<String, BinaryFieldMetadata> newField : newFields.entrySet()) {
                 BinaryFieldMetadata oldFieldMeta = mergedFields.put(newField.getKey(), newField.getValue());
 
@@ -1005,7 +1014,7 @@ public class BinaryUtils {
 
             // Return either old meta if no changes detected, or new merged meta.
             return changed ? new BinaryMetadata(oldMeta.typeId(), oldMeta.typeName(), mergedFields,
-                oldMeta.affinityKeyFieldName(), mergedSchemas, oldMeta.isEnum()) : oldMeta;
+                oldMeta.affinityKeyFieldName(), mergedSchemas, oldMeta.isEnum(), mergedEnumMap) : oldMeta;
         }
     }
 
@@ -1106,6 +1115,8 @@ public class BinaryUtils {
             return BinaryWriteMode.MAP;
         else if (cls.isEnum())
             return BinaryWriteMode.ENUM;
+        else if (cls == BinaryEnumObjectImpl.class)
+            return BinaryWriteMode.BINARY_ENUM;
         else if (cls == Class.class)
             return BinaryWriteMode.CLASS;
         else if (Proxy.class.isAssignableFrom(cls))
@@ -1627,6 +1638,17 @@ public class BinaryUtils {
      *
      * @param in Input stream.
      * @param ctx Binary context.
+     * @return Enum.
+     */
+    public static BinaryEnumObjectImpl doReadBinaryEnum(BinaryInputStream in, BinaryContext ctx) {
+        return doReadBinaryEnum(in, ctx, doReadEnumType(in));
+    }
+
+    /**
+     * Read binary enum.
+     *
+     * @param in Input stream.
+     * @param ctx Binary context.
      * @param type Plain type.
      * @return Enum.
      */
@@ -1903,6 +1925,7 @@ public class BinaryUtils {
                 return doReadBinaryObject(in, ctx, detach);
 
             case GridBinaryMarshaller.ENUM:
+            case GridBinaryMarshaller.BINARY_ENUM:
                 return doReadBinaryEnum(in, ctx, doReadEnumType(in));
 
             case GridBinaryMarshaller.ENUM_ARR:
@@ -2356,6 +2379,85 @@ public class BinaryUtils {
     }
 
     /**
+     * Checks enum values mapping.
+     *
+     * @param typeName Name of the type.
+     * @param enumValues Enum name to ordinal mapping.
+     * @throws BinaryObjectException
+     */
+    public static void validateEnumValues(String typeName, @Nullable Map<String, Integer> enumValues)
+            throws BinaryObjectException {
+
+        if (enumValues == null)
+            return;
+
+        Map<Integer, String> tmpMap = new LinkedHashMap<>(enumValues.size());
+        for (Map.Entry<String, Integer> e: enumValues.entrySet()) {
+
+            String prevName = tmpMap.put(e.getValue(), e.getKey());
+
+            if (prevName != null)
+                throw new BinaryObjectException("Conflicting enum values. Name '" + e.getKey() +
+                        "' uses ordinal value (" + e.getValue() +
+                        ") that is also used for name '" + prevName +
+                        "' [typeName='" + typeName + "']");
+        }
+    }
+
+    /**
+     * Merges enum value mappings and checks for conflicts.
+     *
+     * Possible conflicts:
+     * - same name is used for different ordinal values.
+     * - ordinal value is used more than once.
+     *
+     * @param typeName Name of the type.
+     * @param oldValues Old enum value mapping.
+     * @param newValues New enum value mapping.
+     * @throws BinaryObjectException in case of name or value conflict.
+     */
+    public static Map<String, Integer> mergeEnumValues(String typeName,
+            @Nullable Map<String, Integer> oldValues,
+            Map<String, Integer> newValues)
+            throws BinaryObjectException {
+
+        assert newValues != null;
+
+        int size = (oldValues != null) ? oldValues.size() + newValues.size() : newValues.size();
+
+        Map<Integer, String> revMap = new LinkedHashMap<>(size);
+        Map<String, Integer> mergedMap = new LinkedHashMap<>(size);
+
+        if (oldValues != null) {
+            //assuming that old values were validated earlier once.
+            for (Map.Entry<String, Integer> e : oldValues.entrySet()) {
+                revMap.put(e.getValue(), e.getKey());
+                mergedMap.put(e.getKey(), e.getValue());
+            }
+        }
+
+        for (Map.Entry<String, Integer> e: newValues.entrySet()) {
+            String prevName = revMap.put(e.getValue(), e.getKey());
+
+            if (prevName != null && !prevName.equals(e.getKey()))
+                throw new BinaryObjectException("Conflicting enum values. Name '" + e.getKey() +
+                        "' uses ordinal value (" + e.getValue() +
+                        ") that is also used for name '" + prevName +
+                        "' [typeName='" + typeName + "']");
+
+            Integer prevVal = mergedMap.put(e.getKey(), e.getValue());
+
+            if (prevVal != null && !prevVal.equals(e.getValue()))
+                throw new BinaryObjectException("Conflicting enum values. Value (" + e.getValue() +
+                        ") has name '" + e.getKey() +
+                        "' that is also used for value '" + prevVal +
+                        "' [typeName='" + typeName + "']");
+        }
+
+        return mergedMap;
+    }
+
+    /**
      * Enum type.
      */
     private static class EnumType {

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java
index 7efe4b3..f2ba779 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java
@@ -820,15 +820,23 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
 
         int typeId = val.typeId();
 
-        out.unsafeEnsure(1 + 4);
+        if (typeId != GridBinaryMarshaller.UNREGISTERED_TYPE_ID) {
+            out.unsafeEnsure(1 + 4 + 4);
 
-        out.unsafeWriteByte(GridBinaryMarshaller.ENUM);
-        out.unsafeWriteInt(typeId);
+            out.unsafeWriteByte(GridBinaryMarshaller.BINARY_ENUM);
+            out.unsafeWriteInt(typeId);
+            out.unsafeWriteInt(val.enumOrdinal());
+        }
+        else {
+            out.unsafeEnsure(1 + 4);
+
+            out.unsafeWriteByte(GridBinaryMarshaller.BINARY_ENUM);
+            out.unsafeWriteInt(typeId);
 
-        if (typeId == GridBinaryMarshaller.UNREGISTERED_TYPE_ID)
             doWriteString(val.className());
 
-        out.writeInt(val.enumOrdinal());
+            out.writeInt(val.enumOrdinal());
+        }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java
index d4b0ff4..291c638 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java
@@ -153,6 +153,9 @@ public class GridBinaryMarshaller {
     /** Time array. */
     public static final byte TIME_ARR = 37;
 
+    /** Binary enum */
+    public static final byte BINARY_ENUM = 38;
+
     /** */
     public static final byte NULL = (byte)101;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java
index 6974176..b1a8da9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.binary.builder;
 
 import java.util.Collection;
 import java.util.IdentityHashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.internal.binary.BinaryMetadata;
@@ -115,7 +116,14 @@ class BinaryBuilderSerializer {
             int typeId = writer.context().typeId(clsName);
             String typeName = writer.context().userTypeName(clsName);
 
-            BinaryMetadata meta = new BinaryMetadata(typeId, typeName, null, null, null, true);
+            Object[] enumVals = val.getClass().getEnumConstants();
+
+            Map<String, Integer> enumMap = new LinkedHashMap<>(enumVals.length);
+
+            for (Object enumVal : enumVals)
+                enumMap.put(((Enum)enumVal).name(), ((Enum)enumVal).ordinal());
+
+            BinaryMetadata meta = new BinaryMetadata(typeId, typeName, null, null, null, true, enumMap);
 
             writer.context().updateMetadata(typeId, meta);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
index 02e06fd..d6cd5ca 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
@@ -350,7 +350,7 @@ public class BinaryObjectBuilderImpl implements BinaryObjectBuilder {
                 BinarySchema curSchema = writer.currentSchema();
 
                 ctx.updateMetadata(typeId, new BinaryMetadata(typeId, typeName, fieldsMeta,
-                    ctx.affinityKeyFieldName(typeId), Collections.singleton(curSchema), false));
+                    ctx.affinityKeyFieldName(typeId), Collections.singleton(curSchema), false, null));
 
                 schemaReg.addSchema(curSchema.schemaId(), curSchema);
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessor.java
index 1564ff3..4d285ab 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessor.java
@@ -59,10 +59,12 @@ public interface CacheObjectBinaryProcessor extends IgniteCacheObjectProcessor {
      * @param affKeyFieldName Affinity key field name.
      * @param fieldTypeIds Fields map.
      * @param isEnum Enum flag.
+     * @param enumMap Enum name to ordinal mapping.
      * @throws IgniteException In case of error.
      */
     public void updateMetadata(int typeId, String typeName, @Nullable String affKeyFieldName,
-        Map<String, BinaryFieldMetadata> fieldTypeIds, boolean isEnum) throws IgniteException;
+        Map<String, BinaryFieldMetadata> fieldTypeIds, boolean isEnum, @Nullable Map<String, Integer> enumMap)
+        throws IgniteException;
 
     /**
      * @param typeId Type ID.
@@ -102,6 +104,23 @@ public interface CacheObjectBinaryProcessor extends IgniteCacheObjectProcessor {
     public BinaryObject buildEnum(String typeName, int ord) throws IgniteException;
 
     /**
+     * @param typeName Type name.
+     * @param name Name.
+     * @return Enum object.
+     * @throws IgniteException If failed.
+     */
+    public BinaryObject buildEnum(String typeName, String name) throws IgniteException;
+
+    /**
+     * Register enum type
+     *
+     * @param typeName Type name.
+     * @param vals Mapping of enum constant names to ordinals.
+     * @return Binary Type for registered enum.
+     */
+    public BinaryType registerEnum(String typeName, Map<String, Integer> vals) throws IgniteException;
+
+    /**
      * @return Binaries interface.
      * @throws IgniteException If failed.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
index 636d149..14947e9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
@@ -71,6 +71,7 @@ import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.T1;
 import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.A;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteBiTuple;
 import org.apache.ignite.lang.IgniteClosure;
@@ -170,6 +171,10 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
                     return CacheObjectBinaryProcessorImpl.this.metadata(typeId);
                 }
 
+                @Override public BinaryMetadata metadata0(int typeId) throws BinaryObjectException {
+                    return CacheObjectBinaryProcessorImpl.this.metadata0(typeId);
+                }
+
                 @Override public BinaryType metadata(int typeId, int schemaId) throws BinaryObjectException {
                     return CacheObjectBinaryProcessorImpl.this.metadata(typeId, schemaId);
                 }
@@ -207,6 +212,9 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
                                     c.isEnum()
                                 )
                             );
+
+                            if (c.isEnum())
+                                BinaryUtils.validateEnumValues(c.getTypeName(), c.getEnumValues());
                         }
 
                         map.put("typeCfgs", typeCfgsMap);
@@ -399,8 +407,10 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
 
     /** {@inheritDoc} */
     @Override public void updateMetadata(int typeId, String typeName, @Nullable String affKeyFieldName,
-        Map<String, BinaryFieldMetadata> fieldTypeIds, boolean isEnum) throws BinaryObjectException {
-        BinaryMetadata meta = new BinaryMetadata(typeId, typeName, fieldTypeIds, affKeyFieldName, null, isEnum);
+        Map<String, BinaryFieldMetadata> fieldTypeIds, boolean isEnum, @Nullable Map<String, Integer> enumMap)
+        throws BinaryObjectException {
+        BinaryMetadata meta = new BinaryMetadata(typeId, typeName, fieldTypeIds, affKeyFieldName, null, isEnum,
+            enumMap);
 
         binaryCtx.updateMetadata(typeId, meta);
     }
@@ -433,6 +443,17 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
 
     /** {@inheritDoc} */
     @Nullable @Override public BinaryType metadata(final int typeId) {
+        BinaryMetadata meta = metadata0(typeId);
+
+        return meta != null ? meta.wrap(binaryCtx) : null;
+    }
+
+    /**
+     * @param typeId Type ID.
+     * @return Meta data.
+     * @throws IgniteException In case of error.
+     */
+    @Nullable public BinaryMetadata metadata0(final int typeId) {
         BinaryMetadataHolder holder = metadataLocCache.get(typeId);
 
         if (holder == null) {
@@ -466,7 +487,7 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
                 }
             }
 
-            return holder.metadata().wrap(binaryCtx);
+            return holder.metadata();
         }
         else
             return null;
@@ -547,17 +568,58 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
     }
 
     /** {@inheritDoc} */
-    @Override public BinaryObject buildEnum(String typeName, int ord) throws IgniteException {
+    @Override public BinaryObject buildEnum(String typeName, int ord) throws BinaryObjectException {
+        A.notNullOrEmpty(typeName, "enum type name");
+
         int typeId = binaryCtx.typeId(typeName);
 
         typeName = binaryCtx.userTypeName(typeName);
 
-        updateMetadata(typeId, typeName, null, null, true);
+        updateMetadata(typeId, typeName, null, null, true, null);
 
         return new BinaryEnumObjectImpl(binaryCtx, typeId, null, ord);
     }
 
     /** {@inheritDoc} */
+    @Override public BinaryObject buildEnum(String typeName, String name) throws BinaryObjectException {
+        A.notNullOrEmpty(typeName, "enum type name");
+        A.notNullOrEmpty(name, "enum name");
+
+        int typeId = binaryCtx.typeId(typeName);
+
+        BinaryMetadata metadata = metadata0(typeId);
+
+        if (metadata == null)
+            throw new BinaryObjectException("Failed to get metadata for type [typeId=" +
+                    typeId + ", typeName='" + typeName + "']");
+
+        Integer ordinal = metadata.getEnumOrdinalByName(name);
+
+        typeName = binaryCtx.userTypeName(typeName);
+
+        if (ordinal == null)
+            throw new BinaryObjectException("Failed to resolve enum ordinal by name [typeId=" +
+                    typeId + ", typeName='" + typeName + "', name='" + name + "']");
+
+        return new BinaryEnumObjectImpl(binaryCtx, typeId, null, ordinal);
+    }
+
+    /** {@inheritDoc} */
+    @Override public BinaryType registerEnum(String typeName, Map<String, Integer> vals) throws BinaryObjectException {
+        A.notNullOrEmpty(typeName, "enum type name");
+
+        int typeId = binaryCtx.typeId(typeName);
+
+        typeName = binaryCtx.userTypeName(typeName);
+
+        BinaryUtils.validateEnumValues(typeName, vals);
+
+        updateMetadata(typeId, typeName, null, null, true, vals);
+
+        return binaryCtx.metadata(typeId);
+    }
+
+    /** {@inheritDoc} */
     @Override public IgniteBinary binary() throws IgniteException {
         return binaries;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/IgniteBinaryImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/IgniteBinaryImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/IgniteBinaryImpl.java
index 1a2d0a9..e88819b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/IgniteBinaryImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/IgniteBinaryImpl.java
@@ -18,6 +18,8 @@
 package org.apache.ignite.internal.processors.cache.binary;
 
 import java.util.Collection;
+import java.util.Map;
+
 import org.apache.ignite.IgniteBinary;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessor;
@@ -155,6 +157,30 @@ public class IgniteBinaryImpl implements IgniteBinary {
         }
     }
 
+    /** {@inheritDoc} */
+    @Override public BinaryObject buildEnum(String typeName, String name) {
+        guard();
+
+        try {
+            return proc.buildEnum(typeName, name);
+        }
+        finally {
+            unguard();
+        }
+    }
+
+    /** {@inheritDoc} */
+    public BinaryType registerEnum(String typeName, Map<String, Integer> vals) {
+        guard();
+
+        try {
+            return proc.registerEnum(typeName, vals);
+        }
+        finally {
+            unguard();
+        }
+    }
+
     /**
      * @return Binary processor.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/NoOpBinary.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/NoOpBinary.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/NoOpBinary.java
index c1c8fed..32c3be6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/NoOpBinary.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/NoOpBinary.java
@@ -17,6 +17,8 @@
 package org.apache.ignite.internal.processors.cacheobject;
 
 import java.util.Collection;
+import java.util.Map;
+
 import org.apache.ignite.IgniteBinary;
 import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.binary.BinaryObjectBuilder;
@@ -74,6 +76,16 @@ public class NoOpBinary implements IgniteBinary {
     }
 
     /** {@inheritDoc} */
+    @Override public BinaryObject buildEnum(String typeName, String name) {
+        throw unsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Override public BinaryType registerEnum(String typeName, Map<String, Integer> vals) {
+        throw unsupported();
+    }
+
+    /** {@inheritDoc} */
     private BinaryObjectException unsupported() {
         return new BinaryObjectException("Binary marshaller is not configured.");
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
index 090f382..f115a9c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
@@ -82,6 +82,7 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -371,8 +372,19 @@ public class PlatformContextImpl implements PlatformContext {
                             }
                         });
 
+                    Map<String, Integer> enumMap = null;
+
                     boolean isEnum = reader.readBoolean();
 
+                    if (isEnum) {
+                        int size = reader.readInt();
+
+                        enumMap = new LinkedHashMap<>(size);
+
+                        for (int idx = 0; idx < size; idx++)
+                            enumMap.put(reader.readString(), reader.readInt());
+                    }
+
                     // Read schemas
                     int schemaCnt = reader.readInt();
 
@@ -393,7 +405,7 @@ public class PlatformContextImpl implements PlatformContext {
                         }
                     }
 
-                    return new BinaryMetadata(typeId, typeName, fields, affKey, schemas, isEnum);
+                    return new BinaryMetadata(typeId, typeName, fields, affKey, schemas, isEnum, enumMap);
                 }
             }
         );
@@ -474,7 +486,20 @@ public class PlatformContextImpl implements PlatformContext {
                 writer.writeInt(e.getValue().fieldId());
             }
 
-            writer.writeBoolean(meta.isEnum());
+            if (meta.isEnum()) {
+                writer.writeBoolean(true);
+
+                Map<String, Integer> enumMap = meta0.enumMap();
+
+                writer.writeInt(enumMap.size());
+
+                for (Map.Entry<String, Integer> e: enumMap.entrySet()) {
+                    writer.writeString(e.getKey());
+                    writer.writeInt(e.getValue());
+                }
+            }
+            else
+                writer.writeBoolean(false);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java
index 8d95ac8..be43848 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java
@@ -19,12 +19,16 @@ package org.apache.ignite.internal.processors.platform.binary;
 
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.binary.BinaryType;
 import org.apache.ignite.internal.MarshallerPlatformIds;
 import org.apache.ignite.internal.binary.BinaryRawReaderEx;
 import org.apache.ignite.internal.binary.BinaryRawWriterEx;
 import org.apache.ignite.internal.processors.platform.PlatformAbstractTarget;
 import org.apache.ignite.internal.processors.platform.PlatformContext;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Platform binary processor.
  */
@@ -47,6 +51,9 @@ public class PlatformBinaryProcessor extends PlatformAbstractTarget {
     /** */
     private static final int OP_GET_TYPE = 6;
 
+    /** */
+    private static final int OP_REGISTER_ENUM = 7;
+
     /**
      * Constructor.
      *
@@ -122,6 +129,24 @@ public class PlatformBinaryProcessor extends PlatformAbstractTarget {
                 break;
             }
 
+            case OP_REGISTER_ENUM: {
+                String name = reader.readString();
+
+                int cnt = reader.readInt();
+
+                Map<String, Integer> vals = new HashMap<>(cnt);
+
+                for (int i = 0; i< cnt; i++) {
+                    vals.put(reader.readString(), reader.readInt());
+                }
+
+                BinaryType binaryType = platformCtx.kernalContext().grid().binary().registerEnum(name, vals);
+
+                platformCtx.writeMetadata(writer, binaryType.typeId());
+
+                break;
+            }
+
             default:
                 super.processInStreamOutStream(type, reader, writer);
                 break;

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryEnumsSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryEnumsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryEnumsSelfTest.java
index a223022..fd26d4a 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryEnumsSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryEnumsSelfTest.java
@@ -19,10 +19,14 @@ package org.apache.ignite.internal.binary;
 
 import java.io.Serializable;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.concurrent.Callable;
+
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.binary.BinaryObjectException;
 import org.apache.ignite.binary.BinaryTypeConfiguration;
 import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.configuration.BinaryConfiguration;
@@ -31,7 +35,9 @@ import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.IgniteKernal;
 import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
+import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 
 /**
@@ -42,6 +48,9 @@ public class BinaryEnumsSelfTest extends GridCommonAbstractTest {
     /** Cache name. */
     private static String CACHE_NAME = "cache";
 
+    /** Name of the node that starts with bad config */
+    private static String WRONG_CONF_NODE_NAME = "WrongConfNode";
+
     /** Whether to register types or not. */
     private boolean register;
 
@@ -81,8 +90,20 @@ public class BinaryEnumsSelfTest extends GridCommonAbstractTest {
             BinaryConfiguration bCfg = new BinaryConfiguration();
 
             BinaryTypeConfiguration enumCfg = new BinaryTypeConfiguration(EnumType.class.getName());
+
             enumCfg.setEnum(true);
 
+            if (igniteInstanceName.equals(WRONG_CONF_NODE_NAME))
+                enumCfg.setEnumValues(F.asMap(EnumType.ONE.name(),
+                        EnumType.ONE.ordinal(),
+                        EnumType.TWO.name(),
+                        EnumType.ONE.ordinal()));
+            else
+                enumCfg.setEnumValues(F.asMap(EnumType.ONE.name(),
+                        EnumType.ONE.ordinal(),
+                        EnumType.TWO.name(),
+                        EnumType.TWO.ordinal()));
+
             bCfg.setTypeConfigurations(Arrays.asList(enumCfg, new BinaryTypeConfiguration(EnumHolder.class.getName())));
 
             cfg.setBinaryConfiguration(bCfg);
@@ -317,11 +338,14 @@ public class BinaryEnumsSelfTest extends GridCommonAbstractTest {
     public void checkSimpleBuilder(boolean registered) throws Exception {
         startUp(registered);
 
-        BinaryObject binary = node1.binary().buildEnum(EnumType.class.getName(), EnumType.ONE.ordinal());
+        BinaryObject binaryOne = node1.binary().buildEnum(EnumType.class.getName(), EnumType.ONE.ordinal());
+        BinaryObject binaryTwo = node1.binary().buildEnum(EnumType.class.getName(), EnumType.TWO.ordinal());
 
-        cacheBinary1.put(1, binary);
+        cacheBinary1.put(EnumType.ONE.ordinal(), binaryOne);
+        cacheBinary1.put(EnumType.TWO.ordinal(), binaryTwo);
 
-        validateSimple(1, EnumType.ONE, registered);
+        validateSimple(EnumType.ONE.ordinal(), EnumType.ONE, registered);
+        validateSimple(EnumType.TWO.ordinal(), EnumType.TWO, registered);
     }
 
     /**
@@ -409,6 +433,112 @@ public class BinaryEnumsSelfTest extends GridCommonAbstractTest {
     }
 
     /**
+     * Checks ability to get a collection of binary enums from binary type
+     *
+     * @throws Exception
+     */
+    public void testBinaryTypeEnumValues() throws Exception {
+        startUp(false);
+
+        defineEnum();
+
+        BinaryObject binaryOne = node1.binary().buildEnum(EnumType.class.getName(), EnumType.ONE.ordinal());
+        BinaryObject binaryTwo = node1.binary().buildEnum(EnumType.class.getName(), EnumType.TWO.name());
+
+        Collection<BinaryObject> vals = binaryOne.type().enumValues();
+
+        assertEqualsCollections(F.asList(binaryOne, binaryTwo), vals);
+    }
+
+    /**
+     * Checks the enum configuration validation during start up
+     *
+     * @throws Exception
+     */
+    public void testEnumWrongBinaryConfig() throws Exception {
+        this.register = true;
+
+        GridTestUtils.assertThrows(log, new Callable<Object> (){
+            @Override public Object call() throws Exception {
+                startGrid(WRONG_CONF_NODE_NAME);
+
+                return null;
+            }
+        }, IgniteCheckedException.class, "Conflicting enum values");
+    }
+
+    /**
+     * Checks the enum validation during type registration
+     *
+     * @throws Exception
+     */
+    public void testEnumValidation() throws Exception {
+        startUp(false);
+
+        GridTestUtils.assertThrows(log, new Callable<Object> (){
+
+            @Override public Object call() throws Exception {
+
+                node1.binary().registerEnum("invalidEnumType1",
+                    F.asMap(EnumType.ONE.name(), EnumType.ONE.ordinal(),
+                    EnumType.TWO.name(), EnumType.ONE.ordinal()));
+
+                return null;
+            }
+        }, BinaryObjectException.class, "Conflicting enum values");
+    }
+
+    /**
+     * Checks the enum merge
+     *
+     * @throws Exception
+     */
+    public void testEnumMerge() throws Exception {
+        startUp(false);
+
+        final String enumName = "mergedEnum";
+
+        node1.binary().registerEnum(enumName,
+                F.asMap(EnumType.ONE.name(), EnumType.ONE.ordinal()));
+
+        GridTestUtils.assertThrows(log, new Callable<Object> (){
+
+            @Override public Object call() throws Exception {
+
+                node2.binary().registerEnum(enumName,
+                        F.asMap(EnumType.TWO.name(), EnumType.ONE.ordinal()));
+
+                return null;
+            }
+        }, BinaryObjectException.class, "Conflicting enum values. Name ");
+
+        GridTestUtils.assertThrows(log, new Callable<Object> (){
+            @Override public Object call() throws Exception {
+
+                node2.binary().registerEnum(enumName,
+                        F.asMap(EnumType.ONE.name(), EnumType.TWO.ordinal()));
+
+                return null;
+            }
+        }, BinaryObjectException.class, "Conflicting enum values. Value ");
+
+        node2.binary().registerEnum(enumName,
+                F.asMap(EnumType.ONE.name(), EnumType.ONE.ordinal(),
+                        EnumType.TWO.name(), EnumType.TWO.ordinal()));
+
+        Collection<BinaryObject> vals = node1.binary().type(enumName).enumValues();
+        BinaryObject[] values = vals.toArray(new BinaryObject[vals.size()]);
+
+        assertEquals(2, values.length);
+
+        assertEquals(EnumType.ONE.ordinal(), values[0].enumOrdinal());
+        assertEquals(EnumType.TWO.ordinal(), values[1].enumOrdinal());
+
+        assertEquals(EnumType.ONE.name(), values[0].enumName());
+        assertEquals(EnumType.TWO.name(), values[1].enumName());
+    }
+
+    /**
      * Validate simple array.
      *
      * @param registered Registered flag.
@@ -472,6 +602,16 @@ public class BinaryEnumsSelfTest extends GridCommonAbstractTest {
         assertEquals(node2.binary().typeId(EnumType.class.getName()), obj.type().typeId());
 
         assertEquals(val.ordinal(), obj.enumOrdinal());
+
+        if (register)
+            assertEquals(val.name(), obj.enumName());
+    }
+
+    /** Register enum */
+    private void defineEnum() {
+        node1.binary().registerEnum(EnumType.class.getName(),
+                F.asMap(EnumType.ONE.name(), EnumType.ONE.ordinal(),
+                        EnumType.TWO.name(), EnumType.TWO.ordinal()));
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/test/java/org/apache/ignite/internal/binary/TestCachingMetadataHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/TestCachingMetadataHandler.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/TestCachingMetadataHandler.java
index 704c8f3..77cbffe 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/binary/TestCachingMetadataHandler.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/TestCachingMetadataHandler.java
@@ -44,6 +44,11 @@ public class TestCachingMetadataHandler implements BinaryMetadataHandler {
     }
 
     /** {@inheritDoc} */
+    @Override public BinaryMetadata metadata0(int typeId) throws BinaryObjectException {
+        return null;
+    }
+
+    /** {@inheritDoc} */
     @Override public BinaryType metadata(int typeId, int schemaId) throws BinaryObjectException {
         return null;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputeEchoTask.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputeEchoTask.java b/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputeEchoTask.java
index a5a35c1..984cf62 100644
--- a/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputeEchoTask.java
+++ b/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputeEchoTask.java
@@ -110,6 +110,9 @@ public class PlatformComputeEchoTask extends ComputeTaskAdapter<Integer, Object>
     /** Type: ignite uuid. */
     private static final int TYPE_IGNITE_UUID = 22;
 
+    /** Type: binary enum. */
+    private static final int TYPE_BINARY_ENUM = 23;
+
     /** Default cache name. */
     public static final String DEFAULT_CACHE_NAME = "default";
 
@@ -228,6 +231,16 @@ public class PlatformComputeEchoTask extends ComputeTaskAdapter<Integer, Object>
                 case TYPE_IGNITE_UUID:
                     return ignite.cache(DEFAULT_CACHE_NAME).get(TYPE_IGNITE_UUID);
 
+                case TYPE_BINARY_ENUM: {
+                    Map<String, Integer> values = new HashMap<>(2);
+                    values.put("JavaFoo", 1);
+                    values.put("JavaBar", 2);
+
+                    ignite.binary().registerEnum("JavaDynEnum", values);
+
+                    return ignite.binary().buildEnum("JavaDynEnum", "JavaFoo");
+                }
+
                 default:
                     throw new IgniteException("Unknown type: " + type);
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs
index a7794c6..61f90a3 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs
@@ -1140,6 +1140,9 @@ namespace Apache.Ignite.Core.Tests.Binary
             Assert.AreEqual(new[] { TestEnum.Two }, obj.FEnumArr);
         }
 
+        /// <summary>
+        /// Tests the enum metadata.
+        /// </summary>
         [Test]
         public void TestEnumMeta()
         {
@@ -1148,14 +1151,21 @@ namespace Apache.Ignite.Core.Tests.Binary
             // Put to cache to populate metas
             var binEnum = bin.ToBinary<IBinaryObject>(TestEnumRegistered.One);
 
-            Assert.AreEqual(_marsh.GetDescriptor(typeof (TestEnumRegistered)).TypeId, binEnum.GetBinaryType().TypeId);
+            Assert.AreEqual(_marsh.GetDescriptor(typeof(TestEnumRegistered)).TypeId, binEnum.GetBinaryType().TypeId);
             Assert.AreEqual(0, binEnum.EnumValue);
+            Assert.AreEqual("One", binEnum.EnumName);
 
             var meta = binEnum.GetBinaryType();
 
             Assert.IsTrue(meta.IsEnum);
-            Assert.AreEqual(GetTypeName(typeof (TestEnumRegistered)), meta.TypeName);
+            Assert.AreEqual(GetTypeName(typeof(TestEnumRegistered)), meta.TypeName);
             Assert.AreEqual(0, meta.Fields.Count);
+
+            var enumValues = meta.GetEnumValues().OrderBy(x => x.EnumValue).ToArray();
+            Assert.AreEqual(0, enumValues[0].EnumValue);
+            Assert.AreEqual("One", enumValues[0].EnumName);
+            Assert.AreEqual(1, enumValues[1].EnumValue);
+            Assert.AreEqual("Two", enumValues[1].EnumName);
         }
 
         /// <summary>
@@ -1653,26 +1663,30 @@ namespace Apache.Ignite.Core.Tests.Binary
         {
             var binary = _grid.GetBinary();
 
-            int val = (int)TestEnumRegistered.Two;
+            var enumVal = TestEnumRegistered.Two;
+            var intVal = (int) enumVal;
             var typeName = GetTypeName(typeof(TestEnumRegistered));
             var typeId = BinaryUtils.GetStringHashCode(typeName);
 
             var binEnums = new[]
             {
-                binary.BuildEnum(typeof (TestEnumRegistered), val),
-                binary.BuildEnum(typeName, val)
+                binary.BuildEnum(typeof (TestEnumRegistered), intVal),
+                binary.BuildEnum(typeName, intVal),
+                binary.BuildEnum(typeof (TestEnumRegistered), enumVal.ToString()),
+                binary.BuildEnum(typeName, enumVal.ToString())
             };
 
             foreach (var binEnum in binEnums)
             {
                 Assert.IsTrue(binEnum.GetBinaryType().IsEnum);
 
-                Assert.AreEqual(val, binEnum.EnumValue);
+                Assert.AreEqual(intVal, binEnum.EnumValue);
+                Assert.AreEqual(enumVal.ToString(), binEnum.EnumName);
 
                 Assert.AreEqual(string.Format("{0} [typeId={1}, enumValue={2}, enumValueName={3}]",
-                    typeName, typeId, val, (TestEnumRegistered) val), binEnum.ToString());
+                    typeName, typeId, intVal, enumVal), binEnum.ToString());
 
-                Assert.AreEqual((TestEnumRegistered)val, binEnum.Deserialize<TestEnumRegistered>());
+                Assert.AreEqual(enumVal, binEnum.Deserialize<TestEnumRegistered>());
             }
 
             Assert.AreEqual(binEnums[0], binEnums[1]);
@@ -1687,6 +1701,60 @@ namespace Apache.Ignite.Core.Tests.Binary
         }
 
         /// <summary>
+        /// Tests enum registration.
+        /// </summary>
+        [Test]
+        public void TestRegisterEnum()
+        {
+            var binary = _grid.GetBinary();
+
+            // Register enum and verify resulting type.
+            const string typeName = "DotNetDynEnum";
+            var binType = binary.RegisterEnum(typeName, new Dictionary<string, int> {{"Baz", 3}, {"Bar", 4}});
+
+            Assert.AreEqual(typeName, binType.TypeName);
+            Assert.IsTrue(binType.IsEnum);
+
+            var enumFields = binType.GetEnumValues().OrderBy(x => x.EnumValue).ToArray();
+            Assert.AreEqual(new[] {3, 4}, enumFields.Select(x => x.EnumValue));
+            Assert.AreEqual(new[] {"Baz", "Bar"}, enumFields.Select(x => x.EnumName));
+
+            // Build enum values.
+            var binEnum1 = binary.BuildEnum(typeName, 3);
+            var binEnum2 = binary.BuildEnum(typeName, "Baz");
+
+            Assert.AreEqual(binEnum1, binEnum2);
+            Assert.AreEqual("Baz", binEnum1.EnumName);
+            Assert.AreEqual(3, binEnum2.EnumValue);
+
+            // Register additional value explicitly.
+            binary.RegisterEnum(typeName, new Dictionary<string, int> {{"Foo", 6}});
+            binary.RegisterEnum(typeName, new Dictionary<string, int> {{"Foo", 6}, {"Baz", 3}});
+            binType = binary.GetBinaryType(typeName);
+
+            Assert.AreEqual(typeName, binType.TypeName);
+            Assert.IsTrue(binType.IsEnum);
+
+            enumFields = binType.GetEnumValues().OrderBy(x => x.EnumValue).ToArray();
+            Assert.AreEqual(new[] { 3, 4, 6 }, enumFields.Select(x => x.EnumValue));
+            Assert.AreEqual(new[] { "Baz", "Bar", "Foo" }, enumFields.Select(x => x.EnumName));
+
+            // Register existing value with different name.
+            var ex = Assert.Throws<BinaryObjectException>(
+                () => binary.RegisterEnum(typeName, new Dictionary<string, int> {{"Baz1", 3}}));
+
+            Assert.AreEqual(string.Format("Conflicting enum values. Name 'Baz1' uses ordinal value (3) that " +
+                                          "is also used for name 'Baz' [typeName='{0}']", typeName), ex.Message);
+
+            // Register different value with existing name.
+            ex = Assert.Throws<BinaryObjectException>(
+                () => binary.RegisterEnum(typeName, new Dictionary<string, int> {{"Baz", 33}}));
+
+            Assert.AreEqual(string.Format("Conflicting enum values. Value (33) has name 'Baz' that is " +
+                                          "also used for value '3' [typeName='{0}']", typeName), ex.Message);
+        }
+
+        /// <summary>
         /// Tests the compact footer setting.
         /// </summary>
         [Test]
@@ -2102,13 +2170,13 @@ namespace Apache.Ignite.Core.Tests.Binary
         /** <inheritdoc /> */
         public int GetTypeId(string typeName)
         {
-            return typeName == TestTypeName ? TestTypeId : 0;
+            return typeName == TestTypeName ? TestTypeId : BinaryUtils.GetStringHashCode(typeName);
         }
 
         /** <inheritdoc /> */
         public int GetFieldId(int typeId, string fieldName)
         {
-            return 0;
+            return BinaryUtils.GetStringHashCode(fieldName);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
index b9b7a04..1d8ceb9 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
@@ -122,6 +122,9 @@ namespace Apache.Ignite.Core.Tests.Compute
         /** Echo type: IgniteUuid. */
         private const int EchoTypeIgniteUuid = 22;
 
+        /** Echo type: binary enum (created with builder). */
+        private const int EchoTypeBinaryEnum = 23;
+
         /** */
         private const string DefaultCacheName = "default";
 
@@ -940,6 +943,28 @@ namespace Apache.Ignite.Core.Tests.Compute
         /// Tests the echo task returning enum.
         /// </summary>
         [Test]
+        public void TestEchoTaskBinaryEnum()
+        {
+            var res = _grid1.GetCompute().WithKeepBinary()
+                .ExecuteJavaTask<IBinaryObject>(EchoTask, EchoTypeBinaryEnum);
+
+            Assert.AreEqual("JavaFoo", res.EnumName);
+            Assert.AreEqual(1, res.EnumValue);
+
+            var binType = res.GetBinaryType();
+
+            Assert.IsTrue(binType.IsEnum);
+            Assert.AreEqual("JavaDynEnum", binType.TypeName);
+
+            var vals = binType.GetEnumValues().OrderBy(x => x.EnumValue).ToArray();
+            Assert.AreEqual(new[] {1, 2}, vals.Select(x => x.EnumValue));
+            Assert.AreEqual(new[] {"JavaFoo", "JavaBar"}, vals.Select(x => x.EnumName));
+        }
+
+        /// <summary>
+        /// Tests the echo task returning enum.
+        /// </summary>
+        [Test]
         public void TestEchoTaskEnumFromCache()
         {
             var cache = _grid1.GetCache<int, PlatformComputeEnum>(DefaultCacheName);

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core/Binary/BinaryTypeConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/BinaryTypeConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/BinaryTypeConfiguration.cs
index c36b9fd..2d299f3 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/BinaryTypeConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/BinaryTypeConfiguration.cs
@@ -18,6 +18,7 @@
 namespace Apache.Ignite.Core.Binary
 {
     using System;
+    using Apache.Ignite.Core.Impl.Binary;
     using Apache.Ignite.Core.Impl.Common;
 
     /// <summary>
@@ -51,7 +52,7 @@ namespace Apache.Ignite.Core.Binary
             IgniteArgumentCheck.NotNull(type, "type");
 
             TypeName = type.AssemblyQualifiedName;
-            IsEnum = type.IsEnum;
+            IsEnum = BinaryUtils.IsIgniteEnum(type);
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinary.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinary.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinary.cs
index f269681..671efa4 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinary.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinary.cs
@@ -131,5 +131,29 @@ namespace Apache.Ignite.Core.Binary
         /// <param name="value">Enum int value.</param>
         /// <returns>Binary representation of the specified enum value.</returns>
         IBinaryObject BuildEnum(Type type, int value);
+
+        /// <summary>
+        /// Converts enum to a binary form.
+        /// </summary>
+        /// <param name="typeName">Enum type name.</param>
+        /// <param name="valueName">Enum value name.</param>
+        /// <returns>Binary representation of the specified enum value.</returns>
+        IBinaryObject BuildEnum(string typeName, string valueName);
+
+        /// <summary>
+        /// Converts enum to a binary form.
+        /// </summary>
+        /// <param name="type">Enum type.</param>
+        /// <param name="valueName">Enum value name.</param>
+        /// <returns>Binary representation of the specified enum value.</returns>
+        IBinaryObject BuildEnum(Type type, string valueName);
+
+        /// <summary>
+        /// Registers enum type.
+        /// </summary>
+        /// <param name="typeName">Name of the type.</param>
+        /// <param name="values">Mapping of enum value names to int values.</param>
+        /// <returns>Binary type for registered enum.</returns>
+        IBinaryType RegisterEnum(string typeName, IEnumerable<KeyValuePair<string, int>> values);
     }
 }