You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ag...@apache.org on 2015/11/05 14:16:15 UTC
[23/26] ignite git commit: Merged IGNITE-950-new into IGNITE-1282
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/binary/Binarylizable.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/binary/Binarylizable.java b/modules/core/src/main/java/org/apache/ignite/binary/Binarylizable.java
new file mode 100644
index 0000000..d09ffc8
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/binary/Binarylizable.java
@@ -0,0 +1,48 @@
+/*
+ * 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;
+
+/**
+ * Interface that allows to implement custom serialization
+ * logic for binary objects. IgniteObject is not required
+ * to implement this interface, in which case Ignite will automatically
+ * serialize binary objects using reflection.
+ * <p>
+ * This interface, in a way, is analogous to {@link java.io.Externalizable}
+ * interface, which allows users to override default serialization logic,
+ * usually for performance reasons. The only difference here is that binary
+ * serialization is already very fast and implementing custom serialization
+ * logic for binary does not provide significant performance gains.
+ */
+public interface Binarylizable {
+ /**
+ * Writes fields to provided writer.
+ *
+ * @param writer Binary object writer.
+ * @throws BinaryObjectException In case of error.
+ */
+ public void writeBinary(BinaryWriter writer) throws BinaryObjectException;
+
+ /**
+ * Reads fields from provided reader.
+ *
+ * @param reader Binary object reader.
+ * @throws BinaryObjectException In case of error.
+ */
+ public void readBinary(BinaryReader reader) throws BinaryObjectException;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/binary/package-info.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/binary/package-info.java b/modules/core/src/main/java/org/apache/ignite/binary/package-info.java
new file mode 100644
index 0000000..5ebf9d8
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/binary/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * <!-- Package description. -->
+ * Contains Ignite Binary Objects API classes.
+ */
+package org.apache.ignite.binary;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/cache/CacheKeyConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/CacheKeyConfiguration.java b/modules/core/src/main/java/org/apache/ignite/cache/CacheKeyConfiguration.java
new file mode 100644
index 0000000..767b44c
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/cache/CacheKeyConfiguration.java
@@ -0,0 +1,92 @@
+/*
+ * 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.cache;
+
+import java.io.Serializable;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * Configuration defining various aspects of cache keys without explicit usage of annotations on user classes.
+ */
+public class CacheKeyConfiguration implements Serializable {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** Type name. */
+ private String typeName;
+
+ /** Affinity key field name. */
+ private String affKeyFieldName;
+
+ /**
+ * Creates an empty cache key configuration that should be populated via setters.
+ */
+ public CacheKeyConfiguration() {
+ // Convenience no-op constructor.
+ }
+
+ /**
+ * Creates cache key configuration with given type name and affinity field name.
+ *
+ * @param typeName Type name.
+ * @param affKeyFieldName Affinity field name.
+ */
+ public CacheKeyConfiguration(String typeName, String affKeyFieldName) {
+ this.typeName = typeName;
+ this.affKeyFieldName = affKeyFieldName;
+ }
+
+ /**
+ * Sets type name for which affinity field name is being defined.
+ *
+ * @return Type name.
+ */
+ public String getTypeName() {
+ return typeName;
+ }
+
+ /**
+ * @param typeName Type name for which affinity field name is being defined.
+ */
+ public void setTypeName(String typeName) {
+ this.typeName = typeName;
+ }
+
+ /**
+ * Gets affinity key field name.
+ *
+ * @return Affinity key field name.
+ */
+ public String getAffinityKeyFieldName() {
+ return affKeyFieldName;
+ }
+
+ /**
+ * Sets affinity key field name.
+ *
+ * @param affKeyFieldName Affinity key field name.
+ */
+ public void setAffinityKeyFieldName(String affKeyFieldName) {
+ this.affKeyFieldName = affKeyFieldName;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(CacheKeyConfiguration.class, this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/cache/CacheTypeMetadata.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/CacheTypeMetadata.java b/modules/core/src/main/java/org/apache/ignite/cache/CacheTypeMetadata.java
index 95a138d..2b7205b 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/CacheTypeMetadata.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/CacheTypeMetadata.java
@@ -23,9 +23,12 @@ import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
+import javax.cache.CacheException;
import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStore;
+import org.apache.ignite.internal.processors.query.GridQueryProcessor;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteBiTuple;
/**
@@ -47,6 +50,9 @@ public class CacheTypeMetadata implements Serializable {
/** Value class used to store value in cache. */
private String valType;
+ /** Simple value type name that will be used as SQL table name.*/
+ private String simpleValType;
+
/** Optional persistent key fields (needed only if {@link CacheJdbcPojoStore} is used). */
@GridToStringInclude
private Collection<CacheTypeFieldMetadata> keyFields;
@@ -75,22 +81,20 @@ public class CacheTypeMetadata implements Serializable {
@GridToStringInclude
private Map<String, LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>>> grps;
+ /** */
+ @GridToStringInclude
+ private Map<String,String> aliases;
+
/**
* Default constructor.
*/
public CacheTypeMetadata() {
keyFields = new ArrayList<>();
-
valFields = new ArrayList<>();
-
qryFlds = new LinkedHashMap<>();
-
ascFlds = new LinkedHashMap<>();
-
descFlds = new LinkedHashMap<>();
-
txtFlds = new LinkedHashSet<>();
-
grps = new LinkedHashMap<>();
}
@@ -99,25 +103,16 @@ public class CacheTypeMetadata implements Serializable {
*/
public CacheTypeMetadata(CacheTypeMetadata src) {
dbSchema = src.getDatabaseSchema();
-
dbTbl = src.getDatabaseTable();
-
keyType = src.getKeyType();
-
valType = src.getValueType();
-
+ simpleValType = src.simpleValType;
keyFields = new ArrayList<>(src.getKeyFields());
-
valFields = new ArrayList<>(src.getValueFields());
-
qryFlds = new LinkedHashMap<>(src.getQueryFields());
-
ascFlds = new LinkedHashMap<>(src.getAscendingFields());
-
descFlds = new LinkedHashMap<>(src.getDescendingFields());
-
txtFlds = new LinkedHashSet<>(src.getTextFields());
-
grps = new LinkedHashMap<>(src.getGroups());
}
@@ -194,12 +189,28 @@ public class CacheTypeMetadata implements Serializable {
}
/**
+ * Gets simple value type.
+ *
+ * @return Simple value type.
+ */
+ public String getSimpleValueType() {
+ return simpleValType;
+ }
+
+ /**
* Sets value type.
*
* @param valType Value type.
*/
public void setValueType(String valType) {
+ if (this.valType != null)
+ throw new CacheException("Value type can be set only once.");
+
this.valType = valType;
+
+ Class<?> cls = U.classForName(valType, null);
+
+ simpleValType = cls == null ? valType : GridQueryProcessor.typeName(cls);
}
/**
@@ -280,7 +291,10 @@ public class CacheTypeMetadata implements Serializable {
* @param ascFlds Name-to-type map for ascending-indexed fields.
*/
public void setAscendingFields(Map<String, Class<?>> ascFlds) {
- this.ascFlds = ascFlds;
+ if (ascFlds == null)
+ this.ascFlds = ascFlds;
+ else
+ this.ascFlds.putAll(ascFlds);
}
/**
@@ -337,6 +351,25 @@ public class CacheTypeMetadata implements Serializable {
this.grps = grps;
}
+ /**
+ * Sets mapping from full property name in dot notation to an alias that will be used as SQL column name.
+ * Example: {"parent.name" -> "parentName"}.
+ *
+ * @param aliases Aliases.
+ */
+ public void setAliases(Map<String,String> aliases) {
+ this.aliases = aliases;
+ }
+
+ /**
+ * Gets aliases mapping.
+ *
+ * @return Aliases.
+ */
+ public Map<String,String> getAliases() {
+ return aliases;
+ }
+
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(CacheTypeMetadata.class, this);
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/cache/IgniteObject.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/IgniteObject.java b/modules/core/src/main/java/org/apache/ignite/cache/IgniteObject.java
deleted file mode 100644
index ab926ce..0000000
--- a/modules/core/src/main/java/org/apache/ignite/cache/IgniteObject.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.cache;
-
-import java.io.Serializable;
-import org.apache.ignite.portable.PortableException;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Ignite object. Abstracted representation of a binary object form.
- */
-public interface IgniteObject extends Serializable {
- /**
- * Gets object type ID.
- *
- * @return Type ID.
- */
- public int typeId();
-
- /**
- * Gets field value.
- *
- * @param fieldName Field name.
- * @return Field value.
- * @throws PortableException In case of any other error.
- */
- @Nullable public <F> F field(String fieldName) throws PortableException;
-
- /**
- * Checks whether field is set.
- *
- * @param fieldName Field name.
- * @return {@code true} if field is set.
- */
- public boolean hasField(String fieldName);
-
- /**
- * Gets fully deserialized instance of portable object.
- *
- * @return Fully deserialized instance of portable object.
- * @throws org.apache.ignite.portable.PortableInvalidClassException If class doesn't exist.
- * @throws PortableException In case of any other error.
- */
- @Nullable public <T> T deserialize() throws PortableException;
-}
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java b/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java
new file mode 100644
index 0000000..cb84c47
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java
@@ -0,0 +1,217 @@
+/*
+ * 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.cache;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.A;
+
+/**
+ * Query entity is a description of {@link org.apache.ignite.IgniteCache cache} entry (composed of key and value)
+ * in a way of how it must be indexed and can be queried.
+ */
+public class QueryEntity implements Serializable {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** Key type. */
+ private String keyType;
+
+ /** Value type. */
+ private String valType;
+
+ /** Fields available for query. A map from field name to type name. */
+ private LinkedHashMap<String, String> fields = new LinkedHashMap<>();
+
+ /** Aliases. */
+ private Map<String, String> aliases = new HashMap<>();
+
+ /** Collection of query indexes. */
+ private Map<String, QueryIndex> idxs = new HashMap<>();
+
+ /**
+ * Gets key type for this query pair.
+ *
+ * @return Key type.
+ */
+ public String getKeyType() {
+ return keyType;
+ }
+
+ /**
+ * Sets key type for this query pair.
+ *
+ * @param keyType Key type.
+ */
+ public void setKeyType(String keyType) {
+ this.keyType = keyType;
+ }
+
+ /**
+ * Gets value type for this query pair.
+ *
+ * @return Value type.
+ */
+ public String getValueType() {
+ return valType;
+ }
+
+ /**
+ * Sets value type for this query pair.
+ *
+ * @param valType Value type.
+ */
+ public void setValueType(String valType) {
+ this.valType = valType;
+ }
+
+ /**
+ * Gets query fields for this query pair. The order of fields is important as it defines the order
+ * of columns returned by the 'select *' queries.
+ *
+ * @return Field-to-type map.
+ */
+ public LinkedHashMap<String, String> getFields() {
+ return fields;
+ }
+
+ /**
+ * Sets query fields for this query pair. The order if fields is important as it defines the
+ * order of columns returned by the 'select *' queries.
+ *
+ * @param fields Field-to-type map.
+ */
+ public void setFields(LinkedHashMap<String, String> fields) {
+ this.fields = fields;
+ }
+
+ /**
+ * Gets a collection of index entities.
+ *
+ * @return Collection of index entities.
+ */
+ public Collection<QueryIndex> getIndexes() {
+ return idxs.values();
+ }
+
+ /**
+ * Gets aliases map.
+ *
+ * @return Aliases.
+ */
+ public Map<String, String> getAliases() {
+ return aliases;
+ }
+
+ /**
+ * Sets mapping from full property name in dot notation to an alias that will be used as SQL column name.
+ * Example: {"parent.name" -> "parentName"}.
+
+ * @param aliases Aliases map.
+ */
+ public void setAliases(Map<String, String> aliases) {
+ this.aliases = aliases;
+ }
+
+ /**
+ * Sets a collection of index entities.
+ *
+ * @param idxs Collection of index entities.
+ */
+ public void setIndexes(Collection<QueryIndex> idxs) {
+ for (QueryIndex idx : idxs) {
+ if (!F.isEmpty(idx.getFields())) {
+ if (idx.getName() == null)
+ idx.setName(defaultIndexName(idx));
+
+ if (!this.idxs.containsKey(idx.getName()))
+ this.idxs.put(idx.getName(), idx);
+ else
+ throw new IllegalArgumentException("Duplicate index name: " + idx.getName());
+ }
+ }
+ }
+
+ /**
+ * Utility method for building query entities programmatically.
+ */
+ public void addQueryField(String fullName, String type, String alias) {
+ A.notNull(fullName, "fullName");
+ A.notNull(type, "type");
+
+ fields.put(fullName, type);
+
+ if (alias != null)
+ aliases.put(fullName, alias);
+ }
+
+ /**
+ * Ensures that index with the given name exists.
+ *
+ * @param idxName Index name.
+ * @param idxType Index type.
+ */
+ public void ensureIndex(String idxName, QueryIndexType idxType) {
+ QueryIndex idx = idxs.get(idxName);
+
+ if (idx == null) {
+ idx = new QueryIndex();
+
+ idx.setName(idxName);
+ idx.setIndexType(idxType);
+
+ idxs.put(idxName, idx);
+ }
+ else
+ throw new IllegalArgumentException("An index with the same name and of a different type already exists " +
+ "[idxName=" + idxName + ", existingIdxType=" + idx.getIndexType() + ", newIdxType=" + idxType + ']');
+ }
+
+ /**
+ * Generates default index name by concatenating all index field names.
+ *
+ * @param idx Index to build name for.
+ * @return Index name.
+ */
+ public static String defaultIndexName(QueryIndex idx) {
+ StringBuilder idxName = new StringBuilder();
+
+ for (Map.Entry<String, Boolean> field : idx.getFields().entrySet()) {
+ idxName.append(field.getKey());
+
+ idxName.append('_');
+ idxName.append(field.getValue() ? "asc_" : "desc_");
+ }
+
+ for (int i = 0; i < idxName.length(); i++) {
+ char ch = idxName.charAt(i);
+
+ if (Character.isWhitespace(ch))
+ idxName.setCharAt(i, '_');
+ else
+ idxName.setCharAt(i, Character.toLowerCase(ch));
+ }
+
+ idxName.append("idx");
+
+ return idxName.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/cache/QueryIndex.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/QueryIndex.java b/modules/core/src/main/java/org/apache/ignite/cache/QueryIndex.java
new file mode 100644
index 0000000..f12044d
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/cache/QueryIndex.java
@@ -0,0 +1,192 @@
+/*
+ * 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.cache;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+
+/**
+ * Contains list of fields to be indexed. It is possible to provide field name
+ * suffixed with index specific extension, for example for {@link QueryIndexType#SORTED sorted} index
+ * the list can be provided as following {@code (id, name asc, age desc)}.
+ */
+@SuppressWarnings("TypeMayBeWeakened")
+public class QueryIndex implements Serializable {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** Index name. */
+ private String name;
+
+ /** */
+ private LinkedHashMap<String, Boolean> fields;
+
+ /** */
+ private QueryIndexType type;
+
+ /**
+ * Creates an empty index. Should be populated via setters.
+ */
+ public QueryIndex() {
+ // Empty constructor.
+ }
+
+ /**
+ * Creates single-field sorted ascending index.
+ *
+ * @param name Field name.
+ */
+ public QueryIndex(String name) {
+ this(name, QueryIndexType.SORTED, true);
+ }
+
+ /**
+ * Creates single-field sorted index.
+ *
+ * @param name Field name.
+ * @param asc Ascending flag.
+ */
+ public QueryIndex(String name, boolean asc) {
+ this(name, QueryIndexType.SORTED, asc);
+ }
+
+ /**
+ * Creates index for one field.
+ * If index is sorted, then ascending sorting is used by default.
+ * To specify sort order, use the next method.
+ * This constructor should also have a corresponding setter method.
+ */
+ public QueryIndex(String field, QueryIndexType type) {
+ this(Arrays.asList(field), type);
+ }
+
+ /**
+ * Creates index for one field. The last boolean parameter
+ * is ignored for non-sorted indexes.
+ */
+ public QueryIndex(String field, QueryIndexType type, boolean asc) {
+ fields = new LinkedHashMap<>();
+ fields.put(field, asc);
+
+ this.type = type;
+ }
+
+ /**
+ * Creates index for a collection of fields. If index is sorted, fields will be sorted in
+ * ascending order.
+ *
+ * @param fields Collection of fields to create an index.
+ * @param type Index type.
+ */
+ public QueryIndex(Collection<String> fields, QueryIndexType type) {
+ this.fields = new LinkedHashMap<>();
+
+ for (String field : fields)
+ this.fields.put(field, true);
+
+ this.type = type;
+ }
+
+ /**
+ * Creates index for a collection of fields. The order of fields in the created index will be the same
+ * as iteration order in the passed map. Map value defines whether the index will be ascending.
+ *
+ * @param fields Field name to field sort direction for sorted indexes.
+ * @param type Index type.
+ */
+ public QueryIndex(LinkedHashMap<String, Boolean> fields, QueryIndexType type) {
+ this.fields = fields;
+ this.type = type;
+ }
+
+ /**
+ * Gets index name. Will be automatically set if not provided by a user.
+ *
+ * @return Index name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets index name.
+ *
+ * @param name Index name.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Gets fields included in the index.
+ *
+ * @return Collection of index fields.
+ */
+ public LinkedHashMap<String, Boolean> getFields() {
+ return fields;
+ }
+
+ /**
+ * Sets fields included in the index.
+ *
+ * @param fields Collection of index fields.
+ */
+ public void setFields(LinkedHashMap<String, Boolean> fields) {
+ this.fields = fields;
+ }
+
+ /**
+ * @return Gets a collection of field names.
+ */
+ public Collection<String> getFieldNames() {
+ return fields.keySet();
+ }
+
+ /**
+ * Sets a collection of field names altogether with the field sorting direction. Sorting direction will be
+ * ignored for non-sorted indexes.
+ *
+ * @param fields Collection of fields.
+ * @param asc Ascending flag.
+ */
+ public void setFieldNames(Collection<String> fields, boolean asc) {
+ this.fields = new LinkedHashMap<>();
+
+ for (String field : fields)
+ this.fields.put(field, asc);
+ }
+
+ /**
+ * Gets index type.
+ *
+ * @return Index type.
+ */
+ public QueryIndexType getIndexType() {
+ return type;
+ }
+
+ /**
+ * Sets index type.
+ *
+ * @param type Index type.
+ */
+ public void setIndexType(QueryIndexType type) {
+ this.type = type;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/cache/QueryIndexType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/QueryIndexType.java b/modules/core/src/main/java/org/apache/ignite/cache/QueryIndexType.java
new file mode 100644
index 0000000..f9b544d
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/cache/QueryIndexType.java
@@ -0,0 +1,38 @@
+/*
+ * 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.cache;
+
+/**
+ * Index type.
+ */
+public enum QueryIndexType {
+ /**
+ * Sorted index.
+ */
+ SORTED,
+
+ /**
+ * Full-text index.
+ */
+ FULLTEXT,
+
+ /**
+ * Geo-spatial index.
+ */
+ GEOSPATIAL
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
index ae3f21f..af0122f 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
@@ -18,8 +18,22 @@
package org.apache.ignite.configuration;
import java.io.Serializable;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.TreeSet;
import javax.cache.Cache;
+import javax.cache.CacheException;
import javax.cache.configuration.CacheEntryListenerConfiguration;
import javax.cache.configuration.CompleteConfiguration;
import javax.cache.configuration.Factory;
@@ -36,14 +50,26 @@ import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.cache.CacheRebalanceMode;
import org.apache.ignite.cache.CacheTypeMetadata;
import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.cache.QueryIndexType;
import org.apache.ignite.cache.affinity.AffinityFunction;
import org.apache.ignite.cache.affinity.AffinityKeyMapper;
import org.apache.ignite.cache.eviction.EvictionFilter;
import org.apache.ignite.cache.eviction.EvictionPolicy;
+import org.apache.ignite.cache.query.annotations.QueryGroupIndex;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
import org.apache.ignite.cache.query.annotations.QuerySqlFunction;
+import org.apache.ignite.cache.query.annotations.QueryTextField;
import org.apache.ignite.cache.store.CacheStore;
import org.apache.ignite.cache.store.CacheStoreSessionListener;
import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.processors.query.GridQueryIndexDescriptor;
+import org.apache.ignite.internal.processors.query.GridQueryIndexType;
+import org.apache.ignite.internal.util.tostring.GridToStringExclude;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.F;
+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.S;
import org.apache.ignite.internal.util.typedef.internal.U;
@@ -51,14 +77,12 @@ import org.apache.ignite.lang.IgnitePredicate;
import org.apache.ignite.plugin.CachePluginConfiguration;
import org.jetbrains.annotations.Nullable;
-import javax.cache.Cache;
-import javax.cache.configuration.CompleteConfiguration;
-import javax.cache.configuration.Factory;
-import javax.cache.configuration.MutableConfiguration;
-import javax.cache.expiry.ExpiryPolicy;
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.HashSet;
+import static org.apache.ignite.internal.processors.query.GridQueryIndexType.FULLTEXT;
+import static org.apache.ignite.internal.processors.query.GridQueryIndexType.GEO_SPATIAL;
+import static org.apache.ignite.internal.processors.query.GridQueryIndexType.SORTED;
+import static org.apache.ignite.internal.processors.query.GridQueryProcessor._VAL;
+import static org.apache.ignite.internal.processors.query.GridQueryProcessor.isGeometryClass;
+import static org.apache.ignite.internal.processors.query.GridQueryProcessor.isSqlType;
/**
* This class defines grid cache configuration. This configuration is passed to
@@ -330,7 +354,7 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
private boolean sqlEscapeAll;
/** */
- private Class<?>[] indexedTypes;
+ private transient Class<?>[] indexedTypes;
/** */
private int sqlOnheapRowCacheSize = DFLT_SQL_ONHEAP_ROW_CACHE_SIZE;
@@ -347,6 +371,9 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
/** Cache store session listeners. */
private Factory<? extends CacheStoreSessionListener>[] storeSesLsnrs;
+ /** Query entities. */
+ private Collection<QueryEntity> qryEntities;
+
/** Empty constructor (all values are initialized to their defaults). */
public CacheConfiguration() {
/* No-op. */
@@ -411,6 +438,8 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
name = cc.getName();
nearCfg = cc.getNearConfiguration();
nodeFilter = cc.getNodeFilter();
+ pluginCfgs = cc.getPluginConfigurations();
+ qryEntities = cc.getQueryEntities();
rebalanceMode = cc.getRebalanceMode();
rebalanceBatchSize = cc.getRebalanceBatchSize();
rebalanceDelay = cc.getRebalanceDelay();
@@ -435,7 +464,6 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
writeBehindFlushSize = cc.getWriteBehindFlushSize();
writeBehindFlushThreadCnt = cc.getWriteBehindFlushThreadCount();
writeSync = cc.getWriteSynchronizationMode();
- pluginCfgs = cc.getPluginConfigurations();
}
/**
@@ -855,19 +883,19 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
* store implementation in some cases, but it can cause performance
* degradation due to additional serializations and deserializations
* of portable objects. You will also need to have key and value
- * classes on all nodes since portables will be deserialized when
+ * classes on all nodes since binary will be deserialized when
* store is called.
*
- * @return Keep portables in store flag.
+ * @return Keep binary in store flag.
*/
public Boolean isKeepPortableInStore() {
return keepPortableInStore;
}
/**
- * Sets keep portables in store flag.
+ * Sets keep binary in store flag.
*
- * @param keepPortableInStore Keep portables in store flag.
+ * @param keepPortableInStore Keep binary in store flag.
*/
public void setKeepPortableInStore(boolean keepPortableInStore) {
this.keepPortableInStore = keepPortableInStore;
@@ -1577,9 +1605,10 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
*
* @param typeMeta Collection of type metadata.
* @return {@code this} for chaining.
+ * @deprecated Use {@link #setQueryEntities(java.util.Collection)} instead.
*/
public CacheConfiguration<K, V> setTypeMetadata(Collection<CacheTypeMetadata> typeMeta) {
- this.typeMeta = typeMeta;
+ this.typeMeta = new ArrayList<>(typeMeta);
return this;
}
@@ -1734,21 +1763,39 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
* @return {@code this} for chaining.
*/
public CacheConfiguration<K, V> setIndexedTypes(Class<?>... indexedTypes) {
- A.ensure(indexedTypes == null || (indexedTypes.length & 1) == 0,
+ A.notNull(indexedTypes, "indexedTypes");
+
+ int len = indexedTypes.length;
+
+ if (len == 0)
+ return this;
+
+ A.ensure((len & 1) == 0,
"Number of indexed types is expected to be even. Refer to method javadoc for details.");
- if (indexedTypes != null) {
- int len = indexedTypes.length;
+ if (this.indexedTypes != null)
+ throw new CacheException("Indexed types can be set only once.");
- Class<?>[] newIndexedTypes = new Class<?>[len];
+ Class<?>[] newIndexedTypes = new Class<?>[len];
- for (int i = 0; i < len; i++)
- newIndexedTypes[i] = U.box(indexedTypes[i]);
+ for (int i = 0; i < len; i++) {
+ if (indexedTypes[i] == null)
+ throw new NullPointerException("Indexed types array contains null at index: " + i);
- this.indexedTypes = newIndexedTypes;
+ newIndexedTypes[i] = U.box(indexedTypes[i]);
+ }
+
+ if (qryEntities == null)
+ qryEntities = new ArrayList<>();
+
+ for (int i = 0; i < len; i += 2) {
+ Class<?> keyCls = newIndexedTypes[i];
+ Class<?> valCls = newIndexedTypes[i + 1];
+
+ TypeDescriptor desc = processKeyAndValueClasses(keyCls, valCls);
+
+ qryEntities.add(convert(desc));
}
- else
- this.indexedTypes = null;
return this;
}
@@ -1800,6 +1847,32 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
}
/**
+ * Gets a collection of configured query entities.
+ *
+ * @return Query entities configurations.
+ */
+ public Collection<QueryEntity> getQueryEntities() {
+ return qryEntities != null ? qryEntities : Collections.<QueryEntity>emptyList();
+ }
+
+ /**
+ * Sets query entities configuration.
+ *
+ * @param qryEntities Query entities.
+ * @return {@code this} for chaining.
+ */
+ public CacheConfiguration<K, V> setQueryEntities(Collection<QueryEntity> qryEntities) {
+ if (this.qryEntities == null)
+ this.qryEntities = new ArrayList<>(qryEntities);
+ else if (indexedTypes != null)
+ this.qryEntities.addAll(qryEntities);
+ else
+ throw new CacheException("Query entities can be set only once.");
+
+ return this;
+ }
+
+ /**
* Gets topology validator.
* <p>
* See {@link TopologyValidator} for details.
@@ -1889,6 +1962,233 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
return cfg;
}
+ /**
+ * @param desc Type descriptor.
+ * @return Type metadata.
+ */
+ static QueryEntity convert(TypeDescriptor desc) {
+ QueryEntity entity = new QueryEntity();
+
+ // Key and val types.
+ entity.setKeyType(desc.keyClass().getName());
+ entity.setValueType(desc.valueClass().getName());
+
+ for (ClassProperty prop : desc.props.values())
+ entity.addQueryField(prop.fullName(), U.box(prop.type()).getName(), prop.alias());
+
+ QueryIndex txtIdx = null;
+
+ Collection<QueryIndex> idxs = new ArrayList<>();
+
+ for (Map.Entry<String, GridQueryIndexDescriptor> idxEntry : desc.indexes().entrySet()) {
+ GridQueryIndexDescriptor idx = idxEntry.getValue();
+
+ if (idx.type() == FULLTEXT) {
+ assert txtIdx == null;
+
+ txtIdx = new QueryIndex();
+
+ txtIdx.setIndexType(QueryIndexType.FULLTEXT);
+
+ txtIdx.setFieldNames(idx.fields(), true);
+ txtIdx.setName(idxEntry.getKey());
+ }
+ else {
+ Collection<String> grp = new ArrayList<>();
+
+ for (String fieldName : idx.fields())
+ grp.add(idx.descending(fieldName) ? fieldName + " desc" : fieldName);
+
+ QueryIndex sortedIdx = new QueryIndex();
+
+ sortedIdx.setIndexType(idx.type() == SORTED ? QueryIndexType.SORTED : QueryIndexType.GEOSPATIAL);
+
+ LinkedHashMap<String, Boolean> fields = new LinkedHashMap<>();
+
+ for (String f : idx.fields())
+ fields.put(f, !idx.descending(f));
+
+ sortedIdx.setFields(fields);
+
+ sortedIdx.setName(idxEntry.getKey());
+
+ idxs.add(sortedIdx);
+ }
+ }
+
+ if (desc.valueTextIndex()) {
+ if (txtIdx == null) {
+ txtIdx = new QueryIndex();
+
+ txtIdx.setIndexType(QueryIndexType.FULLTEXT);
+
+ txtIdx.setFieldNames(Arrays.asList(_VAL), true);
+ }
+ else
+ txtIdx.getFields().put(_VAL, true);
+ }
+
+ if (txtIdx != null)
+ idxs.add(txtIdx);
+
+ if (!F.isEmpty(idxs))
+ entity.setIndexes(idxs);
+
+ return entity;
+ }
+
+ /**
+ * @param cls Class.
+ * @return Masked class.
+ */
+ private static Class<?> mask(Class<?> cls) {
+ assert cls != null;
+
+ return isSqlType(cls) ? cls : Object.class;
+ }
+
+ /**
+ * @param keyCls Key class.
+ * @param valCls Value class.
+ * @return Type descriptor.
+ */
+ static TypeDescriptor processKeyAndValueClasses(
+ Class<?> keyCls,
+ Class<?> valCls
+ ) {
+ TypeDescriptor d = new TypeDescriptor();
+
+ d.keyClass(keyCls);
+ d.valueClass(valCls);
+
+ processAnnotationsInClass(true, d.keyCls, d, null);
+ processAnnotationsInClass(false, d.valCls, d, null);
+
+ return d;
+ }
+
+ /**
+ * Process annotations for class.
+ *
+ * @param key If given class relates to key.
+ * @param cls Class.
+ * @param type Type descriptor.
+ * @param parent Parent in case of embeddable.
+ */
+ private static void processAnnotationsInClass(boolean key, Class<?> cls, TypeDescriptor type,
+ @Nullable ClassProperty parent) {
+ if (U.isJdk(cls) || isGeometryClass(cls)) {
+ if (parent == null && !key && isSqlType(cls)) { // We have to index primitive _val.
+ String idxName = _VAL + "_idx";
+
+ type.addIndex(idxName, isGeometryClass(cls) ? GEO_SPATIAL : SORTED);
+
+ type.addFieldToIndex(idxName, _VAL, 0, false);
+ }
+
+ return;
+ }
+
+ if (parent != null && parent.knowsClass(cls))
+ throw new CacheException("Recursive reference found in type: " + cls.getName());
+
+ if (parent == null) { // Check class annotation at top level only.
+ QueryTextField txtAnnCls = cls.getAnnotation(QueryTextField.class);
+
+ if (txtAnnCls != null)
+ type.valueTextIndex(true);
+
+ QueryGroupIndex grpIdx = cls.getAnnotation(QueryGroupIndex.class);
+
+ if (grpIdx != null)
+ type.addIndex(grpIdx.name(), SORTED);
+
+ QueryGroupIndex.List grpIdxList = cls.getAnnotation(QueryGroupIndex.List.class);
+
+ if (grpIdxList != null && !F.isEmpty(grpIdxList.value())) {
+ for (QueryGroupIndex idx : grpIdxList.value())
+ type.addIndex(idx.name(), SORTED);
+ }
+ }
+
+ for (Class<?> c = cls; c != null && !c.equals(Object.class); c = c.getSuperclass()) {
+ for (Field field : c.getDeclaredFields()) {
+ QuerySqlField sqlAnn = field.getAnnotation(QuerySqlField.class);
+ QueryTextField txtAnn = field.getAnnotation(QueryTextField.class);
+
+ if (sqlAnn != null || txtAnn != null) {
+ ClassProperty prop = new ClassProperty(field);
+
+ prop.parent(parent);
+
+ processAnnotation(key, sqlAnn, txtAnn, field.getType(), prop, type);
+
+ type.addProperty(prop, true);
+ }
+ }
+
+ for (Method mtd : c.getDeclaredMethods()) {
+ QuerySqlField sqlAnn = mtd.getAnnotation(QuerySqlField.class);
+ QueryTextField txtAnn = mtd.getAnnotation(QueryTextField.class);
+
+ if (sqlAnn != null || txtAnn != null) {
+ if (mtd.getParameterTypes().length != 0)
+ throw new CacheException("Getter with QuerySqlField " +
+ "annotation cannot have parameters: " + mtd);
+
+ ClassProperty prop = new ClassProperty(mtd);
+
+ prop.parent(parent);
+
+ processAnnotation(key, sqlAnn, txtAnn, mtd.getReturnType(), prop, type);
+
+ type.addProperty(prop, true);
+ }
+ }
+ }
+ }
+
+ /**
+ * Processes annotation at field or method.
+ *
+ * @param key If given class relates to key.
+ * @param sqlAnn SQL annotation, can be {@code null}.
+ * @param txtAnn H2 text annotation, can be {@code null}.
+ * @param cls Class of field or return type for method.
+ * @param prop Current property.
+ * @param desc Class description.
+ */
+ private static void processAnnotation(boolean key, QuerySqlField sqlAnn, QueryTextField txtAnn,
+ Class<?> cls, ClassProperty prop, TypeDescriptor desc) {
+ if (sqlAnn != null) {
+ processAnnotationsInClass(key, cls, desc, prop);
+
+ if (!sqlAnn.name().isEmpty())
+ prop.alias(sqlAnn.name());
+
+ if (sqlAnn.index()) {
+ String idxName = prop.alias() + "_idx";
+
+ desc.addIndex(idxName, isGeometryClass(prop.type()) ? GEO_SPATIAL : SORTED);
+
+ desc.addFieldToIndex(idxName, prop.fullName(), 0, sqlAnn.descending());
+ }
+
+ if (!F.isEmpty(sqlAnn.groups())) {
+ for (String group : sqlAnn.groups())
+ desc.addFieldToIndex(group, prop.fullName(), 0, false);
+ }
+
+ if (!F.isEmpty(sqlAnn.orderedGroups())) {
+ for (QuerySqlField.Group idx : sqlAnn.orderedGroups())
+ desc.addFieldToIndex(idx.name(), prop.fullName(), idx.order(), idx.descending());
+ }
+ }
+
+ if (txtAnn != null)
+ desc.addFieldToTextIndex(prop.fullName());
+ }
+
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(CacheConfiguration.class, this);
@@ -1908,10 +2208,318 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
/** {@inheritDoc} */
@Override public boolean equals(Object obj) {
- if (obj == null)
- return false;
+ return obj != null && obj.getClass().equals(this.getClass());
+ }
+ }
+
+ /**
+ * Descriptor of type.
+ */
+ private static class TypeDescriptor {
+ /** Value field names and types with preserved order. */
+ @GridToStringInclude
+ private final Map<String, Class<?>> fields = new LinkedHashMap<>();
+
+ /** */
+ @GridToStringExclude
+ private final Map<String, ClassProperty> props = new LinkedHashMap<>();
+
+ /** */
+ @GridToStringInclude
+ private final Map<String, IndexDescriptor> indexes = new HashMap<>();
+
+ /** */
+ private IndexDescriptor fullTextIdx;
+
+ /** */
+ private Class<?> keyCls;
+
+ /** */
+ private Class<?> valCls;
+
+ /** */
+ private boolean valTextIdx;
+
+ /**
+ * @return Indexes.
+ */
+ public Map<String, GridQueryIndexDescriptor> indexes() {
+ return Collections.<String, GridQueryIndexDescriptor>unmodifiableMap(indexes);
+ }
+
+ /**
+ * Adds index.
+ *
+ * @param idxName Index name.
+ * @param type Index type.
+ * @return Index descriptor.
+ */
+ public IndexDescriptor addIndex(String idxName, GridQueryIndexType type) {
+ IndexDescriptor idx = new IndexDescriptor(type);
+
+ if (indexes.put(idxName, idx) != null)
+ throw new CacheException("Index with name '" + idxName + "' already exists.");
+
+ return idx;
+ }
+
+ /**
+ * Adds field to index.
+ *
+ * @param idxName Index name.
+ * @param field Field name.
+ * @param orderNum Fields order number in index.
+ * @param descending Sorting order.
+ */
+ public void addFieldToIndex(String idxName, String field, int orderNum,
+ boolean descending) {
+ IndexDescriptor desc = indexes.get(idxName);
+
+ if (desc == null)
+ desc = addIndex(idxName, SORTED);
+
+ desc.addField(field, orderNum, descending);
+ }
+
+ /**
+ * Adds field to text index.
+ *
+ * @param field Field name.
+ */
+ public void addFieldToTextIndex(String field) {
+ if (fullTextIdx == null) {
+ fullTextIdx = new IndexDescriptor(FULLTEXT);
+
+ indexes.put(null, fullTextIdx);
+ }
+
+ fullTextIdx.addField(field, 0, false);
+ }
+
+ /**
+ * @return Value class.
+ */
+ public Class<?> valueClass() {
+ return valCls;
+ }
+
+ /**
+ * Sets value class.
+ *
+ * @param valCls Value class.
+ */
+ void valueClass(Class<?> valCls) {
+ this.valCls = valCls;
+ }
+
+ /**
+ * @return Key class.
+ */
+ public Class<?> keyClass() {
+ return keyCls;
+ }
+
+ /**
+ * Set key class.
+ *
+ * @param keyCls Key class.
+ */
+ void keyClass(Class<?> keyCls) {
+ this.keyCls = keyCls;
+ }
+
+ /**
+ * Adds property to the type descriptor.
+ *
+ * @param prop Property.
+ * @param failOnDuplicate Fail on duplicate flag.
+ */
+ public void addProperty(ClassProperty prop, boolean failOnDuplicate) {
+ String name = prop.fullName();
+
+ if (props.put(name, prop) != null && failOnDuplicate)
+ throw new CacheException("Property with name '" + name + "' already exists.");
+
+ fields.put(name, prop.type());
+ }
+
+ /**
+ * @return {@code true} If we need to have a fulltext index on value.
+ */
+ public boolean valueTextIndex() {
+ return valTextIdx;
+ }
+
+ /**
+ * Sets if this value should be text indexed.
+ *
+ * @param valTextIdx Flag value.
+ */
+ public void valueTextIndex(boolean valTextIdx) {
+ this.valTextIdx = valTextIdx;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(TypeDescriptor.class, this);
+ }
+ }
+
+ /**
+ * Index descriptor.
+ */
+ private static class IndexDescriptor implements GridQueryIndexDescriptor {
+ /** Fields sorted by order number. */
+ private final Collection<T2<String, Integer>> fields = new TreeSet<>(
+ new Comparator<T2<String, Integer>>() {
+ @Override public int compare(T2<String, Integer> o1, T2<String, Integer> o2) {
+ if (o1.get2().equals(o2.get2())) // Order is equal, compare field names to avoid replace in Set.
+ return o1.get1().compareTo(o2.get1());
+
+ return o1.get2() < o2.get2() ? -1 : 1;
+ }
+ });
+
+ /** Fields which should be indexed in descending order. */
+ private Collection<String> descendings;
+
+ /** */
+ private final GridQueryIndexType type;
+
+ /**
+ * @param type Type.
+ */
+ private IndexDescriptor(GridQueryIndexType type) {
+ assert type != null;
+
+ this.type = type;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Collection<String> fields() {
+ Collection<String> res = new ArrayList<>(fields.size());
+
+ for (T2<String, Integer> t : fields)
+ res.add(t.get1());
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean descending(String field) {
+ return descendings != null && descendings.contains(field);
+ }
+
+ /**
+ * Adds field to this index.
+ *
+ * @param field Field name.
+ * @param orderNum Field order number in this index.
+ * @param descending Sort order.
+ */
+ public void addField(String field, int orderNum, boolean descending) {
+ fields.add(new T2<>(field, orderNum));
+
+ if (descending) {
+ if (descendings == null)
+ descendings = new HashSet<>();
+
+ descendings.add(field);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridQueryIndexType type() {
+ return type;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(IndexDescriptor.class, this);
+ }
+ }
+
+ /**
+ * Description of type property.
+ */
+ private static class ClassProperty {
+ /** */
+ private final Member member;
+
+ /** */
+ private ClassProperty parent;
+
+ /** */
+ private String name;
+
+ /** */
+ private String alias;
+
+ /**
+ * Constructor.
+ *
+ * @param member Element.
+ */
+ ClassProperty(Member member) {
+ this.member = member;
+
+ name = member instanceof Method && member.getName().startsWith("get") && member.getName().length() > 3 ?
+ member.getName().substring(3) : member.getName();
+
+ ((AccessibleObject) member).setAccessible(true);
+ }
+
+ /**
+ * @param alias Alias.
+ */
+ public void alias(String alias) {
+ this.alias = alias;
+ }
+
+ /**
+ * @return Alias.
+ */
+ String alias() {
+ return F.isEmpty(alias) ? name : alias;
+ }
+
+ /**
+ * @return Type.
+ */
+ public Class<?> type() {
+ return member instanceof Field ? ((Field)member).getType() : ((Method)member).getReturnType();
+ }
+
+ /**
+ * @param parent Parent property if this is embeddable element.
+ */
+ public void parent(ClassProperty parent) {
+ this.parent = parent;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(ClassProperty.class, this);
+ }
+
+ /**
+ * @param cls Class.
+ * @return {@code true} If this property or some parent relates to member of the given class.
+ */
+ public boolean knowsClass(Class<?> cls) {
+ return member.getDeclaringClass() == cls || (parent != null && parent.knowsClass(cls));
+ }
+
+ /**
+ * @return Full name with all parents in dot notation.
+ */
+ public String fullName() {
+ assert name != null;
+
+ if (parent == null)
+ return name;
- return obj.getClass().equals(this.getClass());
+ return parent.fullName() + '.' + name;
}
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
index 3d38ed9..a91aa7e 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
@@ -31,6 +31,7 @@ import javax.net.ssl.SSLContext;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.IgniteSystemProperties;
import org.apache.ignite.Ignition;
+import org.apache.ignite.cache.CacheKeyConfiguration;
import org.apache.ignite.cache.store.CacheStoreSessionListener;
import org.apache.ignite.cluster.ClusterGroup;
import org.apache.ignite.cluster.ClusterNode;
@@ -427,6 +428,9 @@ public class IgniteConfiguration {
/** Platform configuration. */
private PlatformConfiguration platformCfg;
+ /** Cache key configuration. */
+ private CacheKeyConfiguration[] cacheKeyCfg;
+
/**
* Creates valid grid configuration with all default values.
*/
@@ -463,6 +467,7 @@ public class IgniteConfiguration {
atomicCfg = cfg.getAtomicConfiguration();
daemon = cfg.isDaemon();
cacheCfg = cfg.getCacheConfiguration();
+ cacheKeyCfg = cfg.getCacheKeyConfiguration();
cacheSanityCheckEnabled = cfg.isCacheSanityCheckEnabled();
connectorCfg = cfg.getConnectorConfiguration();
classLdr = cfg.getClassLoader();
@@ -1950,6 +1955,25 @@ public class IgniteConfiguration {
}
/**
+ * Gets cache key configuration.
+ *
+ * @return Cache key configuration.
+ */
+ public CacheKeyConfiguration[] getCacheKeyConfiguration() {
+ return cacheKeyCfg;
+ }
+
+ /**
+ * Sets cache key configuration.
+ * Cache key configuration defines
+ *
+ * @param cacheKeyCfg Cache key configuration.
+ */
+ public void setCacheKeyCfg(CacheKeyConfiguration... cacheKeyCfg) {
+ this.cacheKeyCfg = cacheKeyCfg;
+ }
+
+ /**
* Gets flag indicating whether cache sanity check is enabled. If enabled, then Ignite
* will perform the following checks and throw an exception if check fails:
* <ul>
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
index ebf83bd..4990dc7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
@@ -49,7 +49,7 @@ import org.apache.ignite.internal.managers.swapspace.GridSwapSpaceManager;
import org.apache.ignite.internal.processors.affinity.GridAffinityProcessor;
import org.apache.ignite.internal.processors.cache.CacheConflictResolutionManager;
import org.apache.ignite.internal.processors.cache.GridCacheProcessor;
-import org.apache.ignite.internal.processors.cache.portable.CacheObjectPortableProcessorImpl;
+import org.apache.ignite.internal.processors.cache.portable.CacheObjectBinaryProcessorImpl;
import org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessor;
import org.apache.ignite.internal.processors.clock.GridClockSource;
import org.apache.ignite.internal.processors.clock.GridClockSyncProcessor;
@@ -830,7 +830,7 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
return res;
if (cls.equals(IgniteCacheObjectProcessor.class))
- return (T)new CacheObjectPortableProcessorImpl(this);
+ return (T)new CacheObjectBinaryProcessorImpl(this);
if (cls.equals(CacheConflictResolutionManager.class))
return null;
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
index a7e62b0..88e697c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
@@ -64,7 +64,7 @@ import org.apache.ignite.IgniteException;
import org.apache.ignite.IgniteFileSystem;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.IgniteMessaging;
-import org.apache.ignite.IgnitePortables;
+import org.apache.ignite.IgniteBinary;
import org.apache.ignite.IgniteQueue;
import org.apache.ignite.IgniteScheduler;
import org.apache.ignite.IgniteServices;
@@ -102,8 +102,8 @@ import org.apache.ignite.internal.processors.cache.GridCacheProcessor;
import org.apache.ignite.internal.processors.cache.GridCacheUtilityKey;
import org.apache.ignite.internal.processors.cache.IgniteCacheProxy;
import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
-import org.apache.ignite.internal.processors.cache.portable.CacheObjectPortableProcessor;
-import org.apache.ignite.internal.processors.cache.portable.CacheObjectPortableProcessorImpl;
+import org.apache.ignite.internal.processors.cache.portable.CacheObjectBinaryProcessor;
+import org.apache.ignite.internal.processors.cache.portable.CacheObjectBinaryProcessorImpl;
import org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessor;
import org.apache.ignite.internal.processors.clock.GridClockSyncProcessor;
import org.apache.ignite.internal.processors.closure.GridClosureProcessor;
@@ -157,7 +157,6 @@ import org.apache.ignite.lifecycle.LifecycleBean;
import org.apache.ignite.lifecycle.LifecycleEventType;
import org.apache.ignite.marshaller.MarshallerExclusions;
import org.apache.ignite.marshaller.optimized.OptimizedMarshaller;
-import org.apache.ignite.marshaller.portable.PortableMarshaller;
import org.apache.ignite.mxbean.ClusterLocalNodeMetricsMXBean;
import org.apache.ignite.mxbean.IgniteMXBean;
import org.apache.ignite.mxbean.ThreadPoolMXBean;
@@ -1490,6 +1489,8 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
mgr.start();
}
catch (IgniteCheckedException e) {
+ U.error(log, "Failed to start manager: " + mgr , e);
+
throw new IgniteCheckedException("Failed to start manager: " + mgr, e);
}
}
@@ -2789,8 +2790,10 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
}
/** {@inheritDoc} */
- @Override public IgnitePortables portables() {
- return ((CacheObjectPortableProcessor)ctx.cacheObjects()).portables();
+ @Override public IgniteBinary binary() {
+ IgniteCacheObjectProcessor objProc = ctx.cacheObjects();
+
+ return objProc.binary();
}
/** {@inheritDoc} */
@@ -3088,7 +3091,7 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
return comp;
if (cls.equals(IgniteCacheObjectProcessor.class))
- return (T)new CacheObjectPortableProcessorImpl(ctx);
+ return (T)new CacheObjectBinaryProcessorImpl(ctx);
if (cls.equals(DiscoveryNodeValidationProcessor.class))
return (T)new OsDiscoveryNodeValidationProcessor(ctx);
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientCompute.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientCompute.java b/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientCompute.java
index c907779..e7255f9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientCompute.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/client/GridClientCompute.java
@@ -414,7 +414,7 @@ public interface GridClientCompute {
public GridClientFuture<List<GridClientNode>> refreshTopologyAsync(boolean includeAttrs, boolean includeMetrics);
/**
- * Sets keep portables flag for the next task execution in the current thread.
+ * Sets keep binary flag for the next task execution in the current thread.
*/
public GridClientCompute withKeepPortables();
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnection.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnection.java
index fedd15a..8bdb1d0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnection.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnection.java
@@ -313,7 +313,7 @@ public abstract class GridClientConnection {
* @param taskName Task name.
* @param arg Task argument.
* @param destNodeId Destination node ID.
- * @param keepPortables Keep portables flag.
+ * @param keepPortables Keep binary flag.
* @return Task execution result.
* @throws GridClientConnectionResetException In case of error.
* @throws GridClientClosedException If client was manually closed before request was sent over network.
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManagerAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManagerAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManagerAdapter.java
index f1a9af1..dedee10 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManagerAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientConnectionManagerAdapter.java
@@ -483,7 +483,7 @@ public abstract class GridClientConnectionManagerAdapter implements GridClientCo
}
/**
- * @return Get thread local used to enable keep portables mode.
+ * @return Get thread local used to enable keep binary mode.
*/
protected ThreadLocal<Boolean> keepPortablesThreadLocal() {
return null;
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientNioTcpConnection.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientNioTcpConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientNioTcpConnection.java
index eee2858..24c9c70 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientNioTcpConnection.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/client/impl/connection/GridClientNioTcpConnection.java
@@ -385,7 +385,7 @@ public class GridClientNioTcpConnection extends GridClientConnection {
*
* @param msg Message to request,
* @param destId Destination node identifier.
- * @param keepPortables Keep portables flag.
+ * @param keepPortables Keep binary flag.
* @return Response object.
* @throws GridClientConnectionResetException If request failed.
* @throws GridClientClosedException If client was closed.
@@ -1037,7 +1037,7 @@ public class GridClientNioTcpConnection extends GridClientConnection {
/** Flag indicating if connected message is a forwarded. */
private final boolean forward;
- /** Keep portables flag. */
+ /** Keep binary flag. */
private final boolean keepPortables;
/** Pending message for this future. */
@@ -1101,7 +1101,7 @@ public class GridClientNioTcpConnection extends GridClientConnection {
}
/**
- * @return Keep portables flag.
+ * @return Keep binary flag.
*/
public boolean keepPortables() {
return keepPortables;
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
index 079015c..623da66 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
@@ -31,7 +31,7 @@ import org.apache.ignite.internal.managers.deployment.GridDeploymentInfoBean;
import org.apache.ignite.internal.managers.deployment.GridDeploymentRequest;
import org.apache.ignite.internal.managers.deployment.GridDeploymentResponse;
import org.apache.ignite.internal.managers.eventstorage.GridEventStorageMessage;
-import org.apache.ignite.internal.portable.PortableObjectImpl;
+import org.apache.ignite.internal.portable.BinaryObjectImpl;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
import org.apache.ignite.internal.processors.cache.CacheEntryInfoCollection;
import org.apache.ignite.internal.processors.cache.CacheEntryPredicateContainsValue;
@@ -680,7 +680,7 @@ public class GridIoMessageFactory implements MessageFactory {
break;
case 113:
- msg = new PortableObjectImpl();
+ msg = new BinaryObjectImpl();
break;
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/internal/managers/swapspace/GridSwapSpaceManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/swapspace/GridSwapSpaceManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/swapspace/GridSwapSpaceManager.java
index f90cf4f..437603a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/swapspace/GridSwapSpaceManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/swapspace/GridSwapSpaceManager.java
@@ -221,22 +221,6 @@ public class GridSwapSpaceManager extends GridManagerAdapter<SwapSpaceSpi> {
}
/**
- * Writes value to swap.
- *
- * @param spaceName Space name.
- * @param key Key.
- * @param val Value.
- * @param ldr Class loader (optional).
- * @throws IgniteCheckedException If failed.
- */
- public void write(@Nullable String spaceName, Object key, @Nullable Object val, @Nullable ClassLoader ldr)
- throws IgniteCheckedException {
- assert key != null;
-
- write(spaceName, new SwapKey(key), marshal(val), ldr);
- }
-
- /**
* Removes value from swap.
*
* @param spaceName Space name.
@@ -284,24 +268,6 @@ public class GridSwapSpaceManager extends GridManagerAdapter<SwapSpaceSpi> {
}
/**
- * Removes value from swap.
- *
- * @param spaceName Space name.
- * @param key Key.
- * @param c Optional closure that takes removed value and executes after actual
- * removing. If there was no value in storage the closure is executed given
- * {@code null} value as parameter.
- * @param ldr Class loader (optional).
- * @throws IgniteCheckedException If failed.
- */
- public void remove(@Nullable String spaceName, Object key, @Nullable IgniteInClosure<byte[]> c,
- @Nullable ClassLoader ldr) throws IgniteCheckedException {
- assert key != null;
-
- remove(spaceName, new SwapKey(key), c, ldr);
- }
-
- /**
* Gets size in bytes for swap space.
*
* @param spaceName Space name.
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryFieldImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryFieldImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryFieldImpl.java
new file mode 100644
index 0000000..b8a25c1
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryFieldImpl.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.portable;
+
+import org.apache.ignite.internal.util.tostring.GridToStringExclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.binary.BinaryField;
+
+/**
+ * Implementation of portable field descriptor.
+ */
+public class BinaryFieldImpl implements BinaryField {
+ /** Well-known object schemas. */
+ @GridToStringExclude
+ private final PortableSchemaRegistry schemas;
+
+ /** Field name. */
+ private final String fieldName;
+
+ /** Pre-calculated field ID. */
+ private final int fieldId;
+
+ /**
+ * Constructor.
+ *
+ * @param schemas Schemas.
+ * @param fieldName Field name.
+ * @param fieldId Field ID.
+ */
+ public BinaryFieldImpl(PortableSchemaRegistry schemas, String fieldName, int fieldId) {
+ assert schemas != null;
+ assert fieldName != null;
+ assert fieldId != 0;
+
+ this.schemas = schemas;
+ this.fieldName = fieldName;
+ this.fieldId = fieldId;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String name() {
+ return fieldName;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean exists(BinaryObject obj) {
+ BinaryObjectEx obj0 = (BinaryObjectEx)obj;
+
+ return fieldOrder(obj0) != PortableSchema.ORDER_NOT_FOUND;
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Override public <T> T value(BinaryObject obj) {
+ BinaryObjectEx obj0 = (BinaryObjectEx)obj;
+
+ int order = fieldOrder(obj0);
+
+ return order != PortableSchema.ORDER_NOT_FOUND ? (T)obj0.fieldByOrder(order) : null;
+ }
+
+ /**
+ * Get relative field offset.
+ *
+ * @param obj Object.
+ * @return Field offset.
+ */
+ private int fieldOrder(BinaryObjectEx obj) {
+ int schemaId = obj.schemaId();
+
+ PortableSchema schema = schemas.schema(schemaId);
+
+ if (schema == null) {
+ schema = obj.createSchema();
+
+ schemas.addSchema(schemaId, schema);
+ }
+
+ assert schema != null;
+
+ return schema.order(fieldId);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(BinaryFieldImpl.class, this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetaDataCollector.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetaDataCollector.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetaDataCollector.java
new file mode 100644
index 0000000..b053a55
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetaDataCollector.java
@@ -0,0 +1,263 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.portable;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.binary.BinaryRawWriter;
+import org.apache.ignite.binary.BinaryWriter;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Writer for meta data collection.
+ */
+class BinaryMetaDataCollector implements BinaryWriter {
+ /** */
+ private final Map<String, String> meta = new HashMap<>();
+
+ /** */
+ private final String typeName;
+
+ /**
+ * @param typeName Type name.
+ */
+ BinaryMetaDataCollector(String typeName) {
+ this.typeName = typeName;
+ }
+
+ /**
+ * @return Field meta data.
+ */
+ Map<String, String> meta() {
+ return meta;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeByte(String fieldName, byte val) throws BinaryObjectException {
+ add(fieldName, byte.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeShort(String fieldName, short val) throws BinaryObjectException {
+ add(fieldName, short.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeInt(String fieldName, int val) throws BinaryObjectException {
+ add(fieldName, int.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeLong(String fieldName, long val) throws BinaryObjectException {
+ add(fieldName, long.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeFloat(String fieldName, float val) throws BinaryObjectException {
+ add(fieldName, float.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeDouble(String fieldName, double val) throws BinaryObjectException {
+ add(fieldName, double.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeChar(String fieldName, char val) throws BinaryObjectException {
+ add(fieldName, char.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeBoolean(String fieldName, boolean val) throws BinaryObjectException {
+ add(fieldName, boolean.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeDecimal(String fieldName, @Nullable BigDecimal val) throws BinaryObjectException {
+ add(fieldName, PortableClassDescriptor.Mode.DECIMAL.typeName());
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeString(String fieldName, @Nullable String val) throws BinaryObjectException {
+ add(fieldName, String.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeUuid(String fieldName, @Nullable UUID val) throws BinaryObjectException {
+ add(fieldName, UUID.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeDate(String fieldName, @Nullable Date val) throws BinaryObjectException {
+ add(fieldName, Date.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeTimestamp(String fieldName, @Nullable Timestamp val) throws BinaryObjectException {
+ add(fieldName, Timestamp.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public <T extends Enum<?>> void writeEnum(String fieldName, T val) throws BinaryObjectException {
+ add(fieldName, Enum.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public <T extends Enum<?>> void writeEnumArray(String fieldName, T[] val) throws BinaryObjectException {
+ add(fieldName, Enum[].class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeObject(String fieldName, @Nullable Object obj) throws BinaryObjectException {
+ add(fieldName, Object.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeByteArray(String fieldName, @Nullable byte[] val) throws BinaryObjectException {
+ add(fieldName, byte[].class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeShortArray(String fieldName, @Nullable short[] val) throws BinaryObjectException {
+ add(fieldName, short[].class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeIntArray(String fieldName, @Nullable int[] val) throws BinaryObjectException {
+ add(fieldName, int[].class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeLongArray(String fieldName, @Nullable long[] val) throws BinaryObjectException {
+ add(fieldName, long[].class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeFloatArray(String fieldName, @Nullable float[] val) throws BinaryObjectException {
+ add(fieldName, float[].class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeDoubleArray(String fieldName, @Nullable double[] val) throws BinaryObjectException {
+ add(fieldName, double[].class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeCharArray(String fieldName, @Nullable char[] val) throws BinaryObjectException {
+ add(fieldName, char[].class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeBooleanArray(String fieldName, @Nullable boolean[] val) throws BinaryObjectException {
+ add(fieldName, boolean[].class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeDecimalArray(String fieldName, @Nullable BigDecimal[] val) throws BinaryObjectException {
+ add(fieldName, PortableClassDescriptor.Mode.DECIMAL_ARR.typeName());
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeStringArray(String fieldName, @Nullable String[] val) throws BinaryObjectException {
+ add(fieldName, String[].class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeUuidArray(String fieldName, @Nullable UUID[] val) throws BinaryObjectException {
+ add(fieldName, UUID[].class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeDateArray(String fieldName, @Nullable Date[] val) throws BinaryObjectException {
+ add(fieldName, Date[].class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeTimestampArray(String fieldName, @Nullable Timestamp[] val) throws BinaryObjectException {
+ add(fieldName, Timestamp[].class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeObjectArray(String fieldName, @Nullable Object[] val) throws BinaryObjectException {
+ add(fieldName, Object[].class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public <T> void writeCollection(String fieldName, @Nullable Collection<T> col)
+ throws BinaryObjectException {
+ add(fieldName, Collection.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public <K, V> void writeMap(String fieldName, @Nullable Map<K, V> map) throws BinaryObjectException {
+ add(fieldName, Map.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public BinaryRawWriter rawWriter() {
+ return (BinaryRawWriter)Proxy.newProxyInstance(getClass().getClassLoader(),
+ new Class<?>[] { BinaryRawWriterEx.class },
+ new InvocationHandler() {
+ @Override public Object invoke(Object proxy, Method mtd, Object[] args) throws Throwable {
+ return null;
+ }
+ });
+ }
+
+ /**
+ * @param name Field name.
+ * @param fieldType Field type.
+ * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
+ */
+ private void add(String name, Class<?> fieldType) throws BinaryObjectException {
+ assert fieldType != null;
+
+ add(name, fieldType.getSimpleName());
+ }
+
+ /**
+ * @param name Field name.
+ * @param fieldTypeName Field type name.
+ * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
+ */
+ private void add(String name, String fieldTypeName) throws BinaryObjectException {
+ assert name != null;
+
+ String oldFieldTypeName = meta.put(name, fieldTypeName);
+
+ if (oldFieldTypeName != null && !oldFieldTypeName.equals(fieldTypeName)) {
+ throw new BinaryObjectException(
+ "Field is written twice with different types [" +
+ "typeName=" + typeName +
+ ", fieldName=" + name +
+ ", fieldTypeName1=" + oldFieldTypeName +
+ ", fieldTypeName2=" + fieldTypeName +
+ ']'
+ );
+ }
+ }
+}
\ No newline at end of file