// 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.
= Ignite.NET and Platform Interoperability

Ignite allows different platforms, such as .NET, Java and C{pp}, to interoperate with each other.
Classes and objects defined and written to Ignite by one platform can be read and used by another platform.

== Identifiers

To achieve interoperability Ignite writes objects using the common binary format. This format encodes object type and
fields using integer identifiers.

To transform an object's type and field names to an integer value, Ignite passes them through two stage:

* Name transformation: full type name and field names are passed to `IBinaryNameMapper` interface and converted to some common form.
* ID transformation: resulting strings are passed to `IBinaryIdMapper` to produce either type ID or field ID.

Mappers can be set either globally in `BinaryConfiguration` or for concrete type in `BinaryTypeConfiguration`.

Java has the same interfaces `BinaryNameMapper` and `BinaryIdMapper`. They are set on `BinaryConfiguration` or `BinaryTypeConfiguration`.

.NET and Java types must map to the same type ID and relevant fields must map to the same field ID.

== Default Behavior

The .NET part of Ignite.NET applies the following conversions by default:

* Name transformation: the `System.Type.FullName` property for non-generics types; field or property name is unchanged.
* ID transformation: names are converted to lower case and then ID is calculated in the same way as in the `java.lang.String.hashCode()` method in Java.

The Java part of Ignite.NET applies the following conversions by default:

* Name transformation: the `Class.getName()` method to get class name; field name is unchanged.
* ID transformation: names are converted to lower case and then `java.lang.String.hashCode()` is used to calculate IDs.

For example, the following two types will automatically map to each other, if they are outside namespaces (.NET) and packages (Java):

[tabs]
--
tab:C#[]
[source,csharp]
----
class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public byte[] Data { get; set; }
}
----
tab:Java[]
[source,java]
----
class Person
{
    public int id;
    public String name;
    public byte[] data;
}
----
--

However, the types are normally within some namespace or package. And naming conventions for packages and namespaces
differ in Java and .NET. It may be problematic to have .NET namespace be the same as Java package.

Simple name mapper (which ignores namespace) can be used to avoid this problem. It should be configured both for .NET and Java:

[tabs]
--
tab:Java Spring XML[]
[source,xml]
----
<bean id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
    ...
    <property name="binaryConfiguration">
        <bean class="org.apache.ignite.configuration.BinaryConfiguration">
            <property name="nameMapper">
                <bean class="org.apache.ignite.binary.BinaryBasicNameMapper">
                    <property name="simpleName" value="true"/>
                </bean>
            </property>
        </bean>
    </property>
    ...
</bean>
----
tab:C#[]
[source,csharp]
----
var cfg = new IgniteConfiguration
{
  BinaryConfiguration = new BinaryConfiguration
  {
    NameMapper = new BinaryBasicNameMapper {IsSimpleName = true}
  }
}
----
tab:app.config[]
[source,xml]
----
<igniteConfiguration>
  <binaryConfiguration>
    <nameMapper type="Apache.Ignite.Core.Binary.BinaryBasicNameMapper, Apache.Ignite.Core" isSimpleName="true" />
  </binaryConfiguration>
</igniteConfiguration>
----
--

== Types Compatibility

[width="100%",cols="1,3",opts="header"]
|===
|`C#`| `Java`
|`bool`| `boolean`
|`byte (*), sbyte`| `byte`
|`short, ushort (*)`| `short`
|`int, uint (*)`| `int`
|`long, ulong (*)`| `long`
|`char`| `char`
|`float`| `float`
|`double`| `double`
|`decimal`| `java.math.BigDecimal (**)`
|`string`| `java.lang.String`
|`Guid`| `java.util.UUID`
|`DateTime`| `java.util.Date, java.sql.Timestamp`
|===
`* byte, ushort, uint, ulong` do not have Java counterparts, and are mapped directly byte-by-byte (no range check).
For example, `byte` value of `200` in C# will result in signed `byte` value of `-56` in Java.

`** Java BigDecimal` has arbitrary size and precision, while C# decimal is fixed to 16 bytes and 28-29 digit precision. Ignite.NET will throw `BinaryObjectException` if a `BigDecimal` value does not fit into `decimal` on deserialization.

`Enum` - In Ignite, Java `writeEnum` can only write ordinal values, but in .NET you can assign any number to the `enumValue`.
So, note that any custom enum-to-primitive value bindings are not taken into account.

[CAUTION]
====
[discrete]
=== DateTime Serialization
DateTime can be Local and UTC; Java Timestamp can only be UTC. Because of that, Ignite.NET can serialize DateTime in
following ways:

* .NET style (can work with non-UTC values, does not work in SQL) and as Timestamp (throws exception on non-UTC values, works properly in SQL).

* Reflective serialization: mark field with `[QuerySqlField]` to enforce Timestamp serialization, or set `BinaryReflectiveSerializer.ForceTimestamp`
to true; this can be done on per-type basis, or globally like this:
`IgniteConfiguration.BinaryConfiguration = new BinaryConfiguration { Serializer = new BinaryReflectiveSerializer { ForceTimestamp = true } }`

* `IBinarizable`: use IBinaryWriter.WriteTimestamp method.

When it is not possible to modify class to mark fields with `[QuerySqlField]` or implement `IBinarizable`, use the `IBinarySerializer` approach.
See link:net-specific/net-serialization[Serialization page] for more details.
====

== Collection Compatibility

Arrays of simple types (from the table above) and arrays of objects are interoperable in all cases. For all other collections
and arrays default behavior (with reflective serialization or `IBinaryWriter.WriteObject`) in Ignite.NET is to use `BinaryFormatter`,
and the result can not be read by Java code (this is done to properly support generics). To write collections in interoperable
format, implement 'IBinarizable' interface and use `IBinaryWriter.WriteCollection`, `IBinaryWriter.WriteDictionary`,
`IBinaryReader.ReadCollection`, `IBinaryReader.ReadDictionary`methods.

== Mixed-Platform Clusters

Ignite, Ignite.NET and Ignite.C{pp} nodes can join the same cluster

All platforms are built on top of Java, so any node can execute Java computations.
However, .NET and C{pp} computations can be executed only by corresponding nodes.

The following Ignite.NET functionality is not supported when there is at least one non-.NET node in the cluster:

* Scan Queries with filter
* Continuous Queries with filter
* ICache.Invoke methods
* ICache.LoadCache with filter
* Services
* IMessaging.RemoteListen
* IEvents.RemoteQuery

Blog post with detailed walk-through: https://ptupitsyn.github.io/Ignite-Multi-Platform-Cluster/[Multi-Platform Ignite Cluster: Java + .NET, window=_blank]

== Compute in Mixed-Platform Clusters

The `ICompute.ExecuteJavaTask` methods work without limitations in any cluster. Other `ICompute` methods will execute
closures only on .NET nodes.
