/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ignite.binary; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.TreeMap; /** * Wrapper for binary object in binary format. Once an object is defined as binary, * Ignite will always store it in memory in the binary format. * User can choose to work either with the binary format or with the deserialized form * (assuming that class definitions are present in the classpath). * <p> * <b>NOTE:</b> user does not need to (and should not) implement this interface directly. * <p> * To work with the binary format directly, user should create a cache projection * over {@code BinaryObject} class and then retrieve individual fields as needed: * <pre name=code class=java> * IgniteCache<BinaryObject, BinaryObject> prj = cache.withKeepBinary(); * * // Convert instance of MyKey to binary format. * // We could also use BinaryObjectBuilder to create the key in binary format directly. * BinaryObject key = ignite.binary().toBinary(new MyKey()); * * BinaryObject val = prj.get(key); * * String field = val.field("myFieldName"); * </pre> * Alternatively, if we have class definitions in the classpath, we may choose to work with deserialized * typed objects at all times. In this case we do incur the deserialization cost. * <pre name=code class=java> * IgniteCache<MyKey.class, MyValue.class> cache = grid.cache(null); * * MyValue val = cache.get(new MyKey()); * * // Normal java getter. * String fieldVal = val.getMyFieldName(); * </pre> * <h1 class="header">Working With Maps and Collections</h1> * All maps and collections in binary objects are serialized automatically. When working * with different platforms, e.g. C++ or .NET, Ignite will automatically pick the most * adequate collection or map in either language. For example, {@link ArrayList} in Java will become * {@code List} in C#, {@link LinkedList} in Java is {@link LinkedList} in C#, {@link HashMap} * in Java is {@code Dictionary} in C#, and {@link TreeMap} in Java becomes {@code SortedDictionary} * in C#, etc. * <h1 class="header">Dynamic Structure Changes</h1> * Since objects are always cached in the binary format, server does not need to * be aware of the class definitions. Moreover, if class definitions are not present or not * used on the server, then clients can continuously change the structure of the binary * objects without having to restart the cluster. For example, if one client stores a * certain class with fields A and B, and another client stores the same class with * fields B and C, then the server-side binary object will have the fields A, B, and C. * As the structure of a binary object changes, the new fields become available for SQL queries * automatically. * <h1 class="header">Building Binary Objects</h1> * Ignite comes with {@link BinaryObjectBuilder} which allows to build binary objects dynamically: * <pre name=code class=java> * BinaryObjectBuilder builder = Ignition.ignite().binary().builder("org.project.MyObject"); * * builder.setField("fieldA", "A"); * builder.setField("fieldB", "B"); * * BinaryObject binaryObj = builder.build(); * </pre> * For the cases when class definition is present * in the class path, it is also possible to populate a standard POJO and then * convert it to binary format, like so: * <pre name=code class=java> * MyObject obj = new MyObject(); * * obj.setFieldA("A"); * obj.setFieldB(123); * * BinaryObject binaryObj = Ignition.ignite().binary().toBinary(obj); * </pre> * <h1 class="header">Binary Type Metadata</h1> * Even though Ignite binary protocol only works with hash codes for type and field names * to achieve better performance, Ignite provides metadata for all binary types which * can be queried ar runtime via any of the {@link org.apache.ignite.IgniteBinary#type(Class)} * methods. Having metadata also allows for proper formatting of {@code BinaryObject.toString()} method, * even when binary objects are kept in binary format only, which may be necessary for audit reasons. */ public interface BinaryObject extends Serializable, Cloneable { /** * Gets type information for this binary object. * * @return Binary object type information. * @throws BinaryObjectException In case of error. */ public BinaryType type() throws BinaryObjectException; /** * Gets field value. * * @param fieldName Field name. * @return Field value. * @throws BinaryObjectException In case of any other error. */ public <F> F field(String fieldName) throws BinaryObjectException; /** * Checks whether field exists in the object. * * @param fieldName Field name. * @return {@code True} if field exists. */ public boolean hasField(String fieldName); /** * Gets fully deserialized instance of binary object. * * @return Fully deserialized instance of binary object. * @throws BinaryInvalidTypeException If class doesn't exist. * @throws BinaryObjectException In case of any other error. */ public <T> T deserialize() throws BinaryObjectException; /** * Copies this binary object. * * @return Copy of this binary object. */ public BinaryObject clone() throws CloneNotSupportedException; /** * Creates a new {@link BinaryObjectBuilder} based on this binary object. The following code * <pre name=code class=java> * BinaryObjectBuilder builder = binaryObject.toBuilder(); * </pre> * is equivalent to * <pre name=code class=java> * BinaryObjectBuilder builder = ignite.binary().builder(binaryObject); * </pre> * * @return Binary object builder. * @throws BinaryObjectException If builder cannot be created. */ public BinaryObjectBuilder toBuilder() throws BinaryObjectException; /** * Get ordinal for this enum object. Use {@link BinaryType#isEnum()} to check if object is of enum type. * * @return Ordinal. * @throws BinaryObjectException If object is not enum. */ public int enumOrdinal() throws BinaryObjectException; }