// 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.
= Binary Marshaller

== Basic Concepts

Binary Marshaller is a component of Ignite that is responsible for data serialization. It has the advantages:

* It enables you to read an arbitrary field from an object's serialized form without full object deserialization.
This ability completely removes the requirement to have the cache key and value classes deployed on the server node's classpath.
* It enables you to add and remove fields from objects of the same type. Given that server nodes do not have model classes
definitions, this ability allows dynamic change to an object's structure, and even allows multiple clients with different versions of class definitions to co-exist.
* It enables you to construct new objects based on a type name without having class definitions at all, hence
allowing dynamic type creation.

Binary objects can be used only when the default binary marshaller is used (i.e. no other marshaller is set to the configuration explicitly).

[NOTE]
====
[discrete]
=== Restrictions
There are several restrictions that are implied by the BinaryObject format implementation:

* Internally, Ignite does not write field and type names but uses a lower-case name hash to identify a field or a type.
It means that fields or types with the same name hash are not allowed. Even though serialization will not work out-of-the-box
in the case of hash collision, Ignite provides a way to resolve this collision at the configuration level.
* For the same reason, BinaryObject format does not allow identical field names on different levels of a class hierarchy.
* If a class implements `Externalizable` interface, Ignite will use `OptimizedMarshaller` instead of the binary one.
The `OptimizedMarshaller` uses `writeExternal()` and `readExternal()` methods to serialize and deserialize objects of
this class which requires adding classes of `Externalizable` objects to the classpath of server nodes.
====

The `IgniteBinary` facade, which can be obtained from an instance of Ignite, contains all the necessary methods to work with binary objects.

[NOTE]
====
[discrete]
=== Automatic Hash Code Calculation and Equals Implementation
There are several restrictions that are implied by the BinaryObject format implementation:

If an object can be serialized into a binary form, then Ignite will calculate its hash code during serialization and
write it to the resulting binary array. Also, Ignite provides a custom implementation of the equals method for the binary
object's comparison needs. This means that you do not need to override the GetHashCode and Equals methods of your custom
keys and values in order for them to be used in Ignite, unless they can not be serialized into the binary form.
For instance, objects of `Externalizable` type cannot be serialized into the binary form and require you to implement
the `hashCode` and `equals` methods manually. See Restrictions section above for more details.
====

== Configuring Binary Objects

In the vast majority of use cases, there is no need to additionally configure binary objects.

However, in a case when you need to override the default type and field IDs calculation, or to plug in `BinarySerializer`,
a `BinaryConfiguration` object should be defined in `IgniteConfiguration`. This object allows specifying a global
name mapper, a global ID mapper, and a global binary serializer as well as per-type mappers and serializers. Wildcards
are supported for per-type configuration, in which case, the provided configuration will be applied to all types
that match the type name template.

[tabs]
--
tab:XML[]
[source,xml]
----
<bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">

  <property name="binaryConfiguration">
    <bean class="org.apache.ignite.configuration.BinaryConfiguration">

      <property name="nameMapper" ref="globalNameMapper"/>
      <property name="idMapper" ref="globalIdMapper"/>

      <property name="typeConfigurations">
        <list>
          <bean class="org.apache.ignite.binary.BinaryTypeConfiguration">
            <property name="typeName" value="org.apache.ignite.examples.*"/>
            <property name="serializer" ref="exampleSerializer"/>
          </bean>
        </list>
      </property>
    </bean>
  </property>
</bean>
----
--

== BinaryObject API

By default, Ignite works with deserialized values as it is the most common use case. To enable `BinaryObject`
processing, a user needs to obtain an instance of `IgniteCache` using the `withKeepBinary()` method. When enabled,
this flag will ensure that objects returned from the cache will be in `BinaryObject` format, when possible. The same
applies to values being passed to the `EntryProcessor` and `CacheInterceptor`.

[NOTE]
====
[discrete]
=== Platform Types
Note that not all types will be represented as `BinaryObject` when the `withKeepBinary()` flag is enabled. There is a
set of 'platform' types that includes primitive types, String, UUID, Date, Timestamp, BigDecimal, Collections,
Maps and arrays of these that will never be represented as a `BinaryObject`.

Note that in the example below key type Integer does not change because it is a platform type.
====

[tabs]
--
tab:Java[]
[source,java]
----
// Create a regular Person object and put it to the cache.
Person person = buildPerson(personId);
ignite.cache("myCache").put(personId, person);

// Get an instance of binary-enabled cache.
IgniteCache<Integer, BinaryObject> binaryCache = ignite.cache("myCache").withKeepBinary();

// Get the above person object in the BinaryObject format.
BinaryObject binaryPerson = binaryCache.get(personId);
----
--

== Modifying Binary Objects Using BinaryObjectBuilder

`BinaryObject` instances are immutable. An instance of `BinaryObjectBuilder` must be used in order to update fields and
create a new `BinaryObject`.

An instance of `BinaryObjectBuilder` can be obtained from `IgniteBinary` facade. The builder may be created using a type
name, in this case the returned builder will contain no fields, or it may be created using an existing `BinaryObject`,
in this case the returned builder will copy all the fields from the given `BinaryObject`.

Another way to get an instance of `BinaryObjectBuilder` is to call `toBuilder()` on an existing instance of a `BinaryObject`.
This will also copy all data from the `BinaryObject` to the created builder.

[NOTE]
====
[discrete]
=== Limitations

* You cannot change the types of existing fields.
* You cannot change the order of enum values or add new constants at the beginning or in the middle of the list of enum's
values. You can add new constants to the end of the list though.
====

Below is an example of using the `BinaryObject` API to process data on server nodes without having user classes deployed
on servers and without actual data deserialization.

[tabs]
--
tab:Java[]
[source,java]
----
// The EntryProcessor is to be executed for this key.
int key = 101;

cache.<Integer, BinaryObject>withKeepBinary().invoke(
  key, new CacheEntryProcessor<Integer, BinaryObject, Object>() {
    public Object process(MutableEntry<Integer, BinaryObject> entry,
                          Object... objects) throws EntryProcessorException {
            // Create builder from the old value.
        BinaryObjectBuilder bldr = entry.getValue().toBuilder();

        //Update the field in the builder.
        bldr.setField("name", "Ignite");

        // Set new value to the entry.
        entry.setValue(bldr.build());

        return null;
     }
  });
----
--

== BinaryObject Type Metadata

As it was mentioned above, binary object structure may be changed at runtime hence it may also be useful to get
information about a particular type that is stored in a cache such as field names, field type names, and affinity
field name. Ignite facilitates this requirement via the `BinaryType` interface.

This interface also introduces a faster version of field getter called `BinaryField`. The concept is similar to java
reflection and allows to cache certain information about the field being read in the `BinaryField` instance, which is
useful when reading the same field from a large collection of binary objects.

[tabs]
--
tab:Java[]
[source,java]
----
Collection<BinaryObject> persons = getPersons();

BinaryField salary = null;

double total = 0;
int cnt = 0;

for (BinaryObject person : persons) {
    if (salary == null)
        salary = person.type().field("salary");

    total += salary.value(person);
    cnt++;
}

double avg = total / cnt;
----
--

== BinaryObject and CacheStore

Setting `withKeepBinary()` on the cache API does not affect the way user objects are passed to a `CacheStore`. This is
intentional because in most cases a single `CacheStore` implementation works either with deserialized classes, or with
`BinaryObject` representations. To control the way objects are passed to the store, the `storeKeepBinary` flag on
`CacheConfiguration` should be used. When this flag is set to `false`, deserialized values will be passed to the store,
otherwise `BinaryObject` representations will be used.

Below is an example pseudo-code implementation of a store working with `BinaryObject`:

[tabs]
--
tab:Java[]
[source,java]
----
public class CacheExampleBinaryStore extends CacheStoreAdapter<Integer, BinaryObject> {
    @IgniteInstanceResource
    private Ignite ignite;

    /** {@inheritDoc} */
    @Override public BinaryObject load(Integer key) {
        IgniteBinary binary = ignite.binary();

        List<?> rs = loadRow(key);

        BinaryObjectBuilder bldr = binary.builder("Person");

        for (int i = 0; i < rs.size(); i++)
            bldr.setField(name(i), rs.get(i));

        return bldr.build();
    }

    /** {@inheritDoc} */
    @Override public void write(Cache.Entry<? extends Integer, ? extends BinaryObject> entry) {
        BinaryObject obj = entry.getValue();

        BinaryType type = obj.type();

        Collection<String> fields = type.fieldNames();

        List<Object> row = new ArrayList<>(fields.size());

        for (String fieldName : fields)
            row.add(obj.field(fieldName));

        saveRow(entry.getKey(), row);
    }
}
----
--

== Binary Name Mapper and Binary ID Mapper

Internally, Ignite never writes full strings for field or type names. Instead, for performance reasons, Ignite writes
integer hash codes for type and field names. Testing has indicated 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, `BinaryNameMapper` and `BinaryIdMapper`
support overriding the automatically generated hash code IDs for the type and field names.

`BinaryNameMapper` - maps type/class and field names to different names.
`BinaryIdMapper` - maps given from `BinaryNameMapper` type and field name to ID that will be used by Ignite in internals.

Ignite provides the following out-of-the-box mappers implementation:

* `BinaryBasicNameMapper` - a basic implementation of `BinaryNameMapper` that returns a full or a simple name of a given
class depending on whether the `setSimpleName(boolean useSimpleName)` property is set.
* `BinaryBasicIdMapper` - a basic implementation of `BinaryIdMapper`. It has a configuration property called
`setLowerCase(boolean isLowerCase)`. If the property is set to `false` then a hash code of given type or field name
will be returned. If the property is set to `true` then a hash code of given type or field name in lower case will be returned.

If you are using Java or .NET clients and do not specify mappers in `BinaryConfiguration`, then Ignite will use
`BinaryBasicNameMapper` and the `simpleName` property will be set to `false`, and `BinaryBasicIdMapper` and the
`lowerCase` property will be set to `true`.

If you are using the C{pp} client and do not specify mappers in `BinaryConfiguration`, then Ignite will use
`BinaryBasicNameMapper` and the `simpleName` property will be set to `true`, and `BinaryBasicIdMapper` and the
`lowerCase` property will be set to `true`.

By default, there is no need to configure anything if you use Java, .NET or C{pp}. Mappers need to be configured if
there is a tricky name conversion when platform interoperability is needed.
