diff --git a/bom/pom.xml b/bom/pom.xml
index b26e103a0a..1c840a2c47 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -21,7 +21,7 @@
21.5
21.0
3.2.2
- 3.0.5
+ 3.0.6
3.11.0
3.3.1
5.5.7
diff --git a/changelog/src/changelog/entries/2024/04/7757.GPU-1413.enhancement b/changelog/src/changelog/entries/2024/04/7757.GPU-1413.enhancement
new file mode 100644
index 0000000000..5d6d14d9e5
--- /dev/null
+++ b/changelog/src/changelog/entries/2024/04/7757.GPU-1413.enhancement
@@ -0,0 +1 @@
+Core: Now it is possible to sort over binary metadata, node reference and micronode non-list fields.
\ No newline at end of file
diff --git a/mdm/orientdb-api/src/main/java/com/gentics/mesh/core/data/MeshVertex.java b/mdm/orientdb-api/src/main/java/com/gentics/mesh/core/data/MeshVertex.java
index 4d8ec2004f..ee268a7306 100644
--- a/mdm/orientdb-api/src/main/java/com/gentics/mesh/core/data/MeshVertex.java
+++ b/mdm/orientdb-api/src/main/java/com/gentics/mesh/core/data/MeshVertex.java
@@ -8,11 +8,13 @@
import com.gentics.graphqlfilter.filter.operation.FilterOperation;
import com.gentics.mesh.context.BulkActionContext;
import com.gentics.mesh.context.impl.DummyBulkActionContext;
+import com.gentics.mesh.core.data.dao.PersistingRootDao;
import com.gentics.mesh.core.data.perm.InternalPermission;
import com.gentics.mesh.core.data.user.HibUser;
import com.gentics.mesh.core.rest.common.ContainerType;
import com.gentics.mesh.graphdb.model.MeshElement;
import com.gentics.mesh.madl.frame.VertexFrame;
+import com.gentics.mesh.parameter.PagingParameters;
import com.tinkerpop.blueprints.Vertex;
/**
@@ -96,4 +98,18 @@ default void delete() {
default String parseFilter(FilterOperation> filter, ContainerType ctype, HibUser user, InternalPermission permission, Optional maybeOwner) {
return parseFilter(filter, ctype) + permissionFilter(user, permission, maybeOwner, Optional.ofNullable(ctype)).map(permFilter -> " AND " + permFilter).orElse(StringUtils.EMPTY);
}
+
+ /**
+ * Set up native permission filter if the sorting is requested, since the sorting forces the native SQL data fetcher.
+ *
+ * @param pagingInfo
+ * @param user
+ * @param permission
+ * @param maybeOwner
+ * @param containerType
+ * @return
+ */
+ default Optional permissionFilterIfRequired(PagingParameters pagingInfo, HibUser user, InternalPermission permission, Optional maybeOwner, Optional containerType) {
+ return PersistingRootDao.shouldSort(pagingInfo) ? permissionFilter(user, permission, maybeOwner, containerType) : Optional.empty();
+ }
}
diff --git a/mdm/orientdb-api/src/main/java/com/gentics/mesh/core/data/relationship/GraphRelationship.java b/mdm/orientdb-api/src/main/java/com/gentics/mesh/core/data/relationship/GraphRelationship.java
index 4b5c9d1841..d4b63c8e00 100644
--- a/mdm/orientdb-api/src/main/java/com/gentics/mesh/core/data/relationship/GraphRelationship.java
+++ b/mdm/orientdb-api/src/main/java/com/gentics/mesh/core/data/relationship/GraphRelationship.java
@@ -1,5 +1,7 @@
package com.gentics.mesh.core.data.relationship;
+import java.util.Optional;
+
/**
* A class for determining the relationship of a vertex class over the edge labels and edge properties
*
@@ -12,6 +14,8 @@ public class GraphRelationship {
private final Class> relatedVertexClass;
private final String edgeFieldName;
private final String defaultEdgeFieldFilterValue;
+ private final Optional maybeEdgeLevelFields;
+ private final boolean skipMapping;
/**
* Constructor
@@ -20,13 +24,43 @@ public class GraphRelationship {
* @param relatedVertexClass a vertex class name, where the edge goes to
* @param edgeFieldName name of an edge property, that is being used in the filtering. If null/empty, no edge property filtering used
* @param defaultEdgeFieldFilterValue default value for the edge property filtering. Unused, if edgeFieldName is null/empty.
+ * @param maybeEdgeLevelFields optional list of entity fields, that are applied on an input edge level.
*/
public GraphRelationship(String edgeName, Class> relatedVertexClass, String edgeFieldName,
- String defaultEdgeFieldFilterValue) {
+ String defaultEdgeFieldFilterValue, Optional maybeEdgeLevelFields) {
+ this(edgeName, relatedVertexClass, edgeFieldName, defaultEdgeFieldFilterValue, maybeEdgeLevelFields, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param edgeName an edge label
+ * @param relatedVertexClass a vertex class name, where the edge goes to
+ * @param edgeFieldName name of an edge property, that is being used in the filtering. If null/empty, no edge property filtering used
+ * @param defaultEdgeFieldFilterValue default value for the edge property filtering. Unused, if edgeFieldName is null/empty.
+ * @param maybeEdgeLevelFields optional list of entity fields, that are applied on an input edge level.
+ * @param skipMapping this mapping is artificial and should not be used in either filtering or sorting.
+ */
+ public GraphRelationship(String edgeName, Class> relatedVertexClass, String edgeFieldName,
+ String defaultEdgeFieldFilterValue, Optional maybeEdgeLevelFields, boolean skipMapping) {
this.edgeName = edgeName;
this.relatedVertexClass = relatedVertexClass;
this.edgeFieldName = edgeFieldName;
this.defaultEdgeFieldFilterValue = defaultEdgeFieldFilterValue;
+ this.maybeEdgeLevelFields = maybeEdgeLevelFields;
+ this.skipMapping = skipMapping;
+ }
+ /**
+ * Constructor with optional edge fields.
+ *
+ * @param edgeName an edge label
+ * @param relatedVertexClass a vertex class name, where the edge goes to
+ * @param edgeFieldName name of an edge property, that is being used in the filtering. If null/empty, no edge property filtering used
+ * @param defaultEdgeFieldFilterValue default value for the edge property filtering. Unused, if edgeFieldName is null/empty.
+ */
+ public GraphRelationship(String edgeName, Class> relatedVertexClass, String edgeFieldName,
+ String defaultEdgeFieldFilterValue) {
+ this(edgeName, relatedVertexClass, edgeFieldName, defaultEdgeFieldFilterValue, Optional.empty());
}
public String getEdgeName() {
return edgeName;
@@ -40,4 +74,11 @@ public String getEdgeFieldName() {
public String getDefaultEdgeFieldFilterValue() {
return defaultEdgeFieldFilterValue;
}
+ public Optional getMaybeEdgeLevelFields() {
+ return maybeEdgeLevelFields;
+ }
+
+ public boolean isSkipMapping() {
+ return skipMapping;
+ }
}
diff --git a/mdm/orientdb-api/src/main/java/com/gentics/mesh/core/data/relationship/GraphRelationships.java b/mdm/orientdb-api/src/main/java/com/gentics/mesh/core/data/relationship/GraphRelationships.java
index 0354b943e6..3b9a6440c8 100644
--- a/mdm/orientdb-api/src/main/java/com/gentics/mesh/core/data/relationship/GraphRelationships.java
+++ b/mdm/orientdb-api/src/main/java/com/gentics/mesh/core/data/relationship/GraphRelationships.java
@@ -4,6 +4,7 @@
import java.util.HashMap;
import java.util.Map;
+import java.util.Optional;
import com.gentics.madl.index.IndexHandler;
import com.gentics.madl.type.TypeHandler;
@@ -19,11 +20,32 @@ public class GraphRelationships {
* Add a relation between entities through an edge.
*/
public static void addRelation(Class keyClass, Class valueClass, String mappingName, String relationName, String edgeFieldName, String defaultEdgeFieldFilterValue) {
+ addRelation(keyClass, valueClass, mappingName, relationName, edgeFieldName, defaultEdgeFieldFilterValue, Optional.empty(), false);
+ }
+
+ /**
+ * Add a relation between entities through an edge, with optional edge fields.
+ */
+ public static void addRelation(Class keyClass, Class valueClass, String mappingName, String relationName, String edgeFieldName, String defaultEdgeFieldFilterValue, Optional maybeEdgeLevelFieldNames, boolean skipMapping) {
Map relations = VERTEX_RELATIONS.getOrDefault(keyClass, new HashMap<>());
- relations.put(mappingName, new GraphRelationship(relationName, valueClass, edgeFieldName, defaultEdgeFieldFilterValue));
+ relations.put(mappingName, new GraphRelationship(relationName, valueClass, edgeFieldName, defaultEdgeFieldFilterValue, maybeEdgeLevelFieldNames, skipMapping));
VERTEX_RELATIONS.put(keyClass, relations);
}
+ /**
+ * Add a relation between entities through UUID.
+ *
+ * @param
+ * @param
+ * @param keyClass
+ * @param valueClass
+ * @param mappingName
+ * @param relationName
+ */
+ public static void addUnmappedRelation(Class keyClass, Class valueClass, String mappingName) {
+ addRelation(keyClass, valueClass, mappingName, MeshVertex.UUID_KEY, mappingName, null, Optional.empty(), true);
+ }
+
/**
* Add a relation between entities through UUID.
*
@@ -35,7 +57,7 @@ public static void addRelation(Clas
* @param relationName
*/
public static void addRelation(Class keyClass, Class valueClass, String mappingName) {
- addRelation(keyClass, valueClass, mappingName, MeshVertex.UUID_KEY, mappingName, null);
+ addRelation(keyClass, valueClass, mappingName, MeshVertex.UUID_KEY, mappingName, null, Optional.empty(), false);
}
/**
diff --git a/mdm/orientdb-api/src/main/java/com/gentics/mesh/graphdb/MeshOrientGraphQuery.java b/mdm/orientdb-api/src/main/java/com/gentics/mesh/graphdb/MeshOrientGraphQuery.java
index f34e71a421..8fb65245c1 100644
--- a/mdm/orientdb-api/src/main/java/com/gentics/mesh/graphdb/MeshOrientGraphQuery.java
+++ b/mdm/orientdb-api/src/main/java/com/gentics/mesh/graphdb/MeshOrientGraphQuery.java
@@ -1,5 +1,6 @@
package com.gentics.mesh.graphdb;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -204,12 +205,24 @@ protected void buildOrderFieldRequest(StringBuilder text, boolean isEdgeRequest,
String sanitizedPart = sanitizeInput(sortParts[0]);
String[] pathParts = sanitizedPart.split("\\.");
text.append(", ");
- Map relation = GraphRelationships.findRelation(currentMapping);
+ Map relation = null;
+ Optional maybeEdgeLevelFields = Optional.empty();
for (int i = 0; i < pathParts.length; i++) {
String pathPart = pathParts[i];
+ relation = GraphRelationships.findRelation(currentMapping);
+ Map localRelation = relation;
+ Optional maybeFieldTypeMapping = Optional.ofNullable(localRelation)
+ .flatMap(relation1 -> relation1.keySet().stream()
+ .filter(key -> key.startsWith("*") && pathPart.matches("[\\S]" + key))
+ .findAny());
if (relation != null && !sanitizedPart.endsWith(pathPart)
- && (relation.containsKey(pathPart) || (relation.containsKey("*")))) {
- GraphRelationship relationMapping = relation.get(pathPart) != null ? relation.get(pathPart) : relation.get("*");
+ && (relation.containsKey(pathPart) || (relation.containsKey("*") || maybeFieldTypeMapping.isPresent()))) {
+ GraphRelationship relationMapping = maybeFieldTypeMapping.map(key -> localRelation.get(key))
+ .or(() -> Optional.ofNullable(localRelation.get(pathPart))).orElseGet(() -> localRelation.get("*"));
+ if (relationMapping.isSkipMapping()) {
+ continue;
+ }
+ maybeEdgeLevelFields = relationMapping.getMaybeEdgeLevelFields();
if (useEdgeFilters && relationMapping != null) {
if (MeshVertex.UUID_KEY.equals(relationMapping.getEdgeName())) {
String partName = pathParts.length > 1 ? pathParts[1] : pathPart;
@@ -230,6 +243,10 @@ protected void buildOrderFieldRequest(StringBuilder text, boolean isEdgeRequest,
escapeFieldNameIfRequired(text, relationMapping.getEdgeFieldName());
text.append(")");
} else {
+ String localPathPart = pathPart;
+ if (maybeFieldTypeMapping.isPresent()) {
+ localPathPart = pathPart.split("-")[0];
+ }
if (i < 1 && isEdgeRequest) {
text.append(relationDirection.name().toLowerCase());
text.append("V().");
@@ -240,10 +257,12 @@ protected void buildOrderFieldRequest(StringBuilder text, boolean isEdgeRequest,
text.append("')[");
text.append(relationMapping.getEdgeFieldName());
text.append("='");
- text.append(relation.get(pathPart) != null ? relationMapping.getDefaultEdgeFieldFilterValue() : pathPart);
+ text.append(localRelation.get(localPathPart) != null ? relationMapping.getDefaultEdgeFieldFilterValue() : localPathPart);
text.append("'].");
- text.append(vertexLookupDirOpposite.name().toLowerCase());
- text.append("V()");
+ if (maybeEdgeLevelFields.isEmpty()) {
+ text.append(vertexLookupDirOpposite.name().toLowerCase());
+ text.append("V()");
+ }
}
} else {
if (i < 1 && isEdgeRequest) {
@@ -255,19 +274,31 @@ protected void buildOrderFieldRequest(StringBuilder text, boolean isEdgeRequest,
escapeFieldNameIfRequired(text, relationMapping.getEdgeName());
text.append(")");
}
- text.append("[0].");
- currentMapping = relationMapping.getRelatedVertexClass();
- } else if (i == 1 && "fields".equals(pathParts[0]) && pathParts.length > 2) {
- // skip the schema name
+ if (maybeEdgeLevelFields.isEmpty()) {
+ text.append("[0].");
+ currentMapping = relationMapping.getRelatedVertexClass();
+ }
+ } else if ((i > 0 && "fields".equals(pathParts[i-1])) || (i < (pathParts.length-1) && "fields".equals(pathParts[i+1])) && pathParts.length > 2) {
+ // skip the schema name or the self-reference
continue;
} else {
if (i < 1 && isEdgeRequest) {
text.append(relationDirection.name().toLowerCase());
text.append("V().");
}
- text.append("`");
- text.append(pathPart);
- text.append("`");
+ maybeEdgeLevelFields
+ .flatMap(edgeLevelFields -> Arrays.stream(edgeLevelFields).filter(field -> field.equals(pathPart)).findAny())
+ .ifPresentOrElse(field -> {
+ text.append("`");
+ text.append(field);
+ text.append("`");
+ text.append("[0]");
+ }, () -> {
+ text.append("`");
+ text.append(pathPart);
+ text.append("`");
+ });
+ maybeEdgeLevelFields = Optional.empty();
}
}
text.append(" as ");
diff --git a/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/container/impl/AbstractGraphFieldContainerImpl.java b/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/container/impl/AbstractGraphFieldContainerImpl.java
index b6cfcd721f..8b3679a848 100644
--- a/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/container/impl/AbstractGraphFieldContainerImpl.java
+++ b/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/container/impl/AbstractGraphFieldContainerImpl.java
@@ -9,9 +9,12 @@
import static io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR;
import java.util.List;
+import java.util.Optional;
import org.apache.commons.lang3.StringUtils;
+import com.gentics.madl.index.IndexHandler;
+import com.gentics.madl.type.TypeHandler;
import com.gentics.mesh.context.BulkActionContext;
import com.gentics.mesh.context.InternalActionContext;
import com.gentics.mesh.core.data.GraphFieldContainer;
@@ -20,6 +23,7 @@
import com.gentics.mesh.core.data.binary.HibBinary;
import com.gentics.mesh.core.data.binary.HibImageVariant;
import com.gentics.mesh.core.data.binary.impl.BinaryGraphFieldVariantImpl;
+import com.gentics.mesh.core.data.binary.impl.BinaryImpl;
import com.gentics.mesh.core.data.impl.GraphFieldTypes;
import com.gentics.mesh.core.data.node.HibNode;
import com.gentics.mesh.core.data.node.Micronode;
@@ -60,7 +64,10 @@
import com.gentics.mesh.core.data.node.field.nesting.MicronodeGraphField;
import com.gentics.mesh.core.data.node.field.nesting.NodeGraphField;
import com.gentics.mesh.core.data.node.impl.MicronodeImpl;
+import com.gentics.mesh.core.data.node.impl.NodeImpl;
+import com.gentics.mesh.core.data.relationship.GraphRelationships;
import com.gentics.mesh.core.data.s3binary.S3HibBinary;
+import com.gentics.mesh.core.data.s3binary.impl.S3BinaryImpl;
import com.gentics.mesh.core.data.schema.HibMicroschemaVersion;
import com.gentics.mesh.core.rest.error.GenericRestException;
import com.gentics.mesh.core.rest.node.FieldMap;
@@ -78,6 +85,26 @@
public abstract class AbstractGraphFieldContainerImpl extends AbstractBasicGraphFieldContainerImpl implements GraphFieldContainer {
static final Logger log = LoggerFactory.getLogger(AbstractGraphFieldContainerImpl.class);
+ /**
+ * Initialize the vertex type and indices.
+ *
+ * @param type
+ * @param index
+ */
+ public static void init(TypeHandler type, IndexHandler index, Class extends AbstractGraphFieldContainerImpl> cls) {
+ GraphRelationships.addRelation(cls, MicronodeImpl.class, "*-micronode", HAS_FIELD, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
+ GraphRelationships.addRelation(cls, NodeImpl.class, "*-node", HAS_FIELD, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
+ GraphRelationships.addRelation(cls, BinaryImpl.class, "*-binary", HAS_FIELD, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY,
+ Optional.of(new String[] { BinaryGraphField.BINARY_IMAGE_DOMINANT_COLOR_PROPERTY_KEY, BinaryGraphField.BINARY_CONTENT_TYPE_PROPERTY_KEY, BinaryGraphField.BINARY_FILENAME_PROPERTY_KEY }), false);
+ GraphRelationships.addRelation(cls, S3BinaryImpl.class, "*-s3binary", HAS_FIELD, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
+ GraphRelationships.addRelation(cls, StringGraphFieldListImpl.class, "*-stringlist", HAS_LIST, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
+ GraphRelationships.addRelation(cls, NumberGraphFieldListImpl.class, "*-numberlist", HAS_LIST, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
+ GraphRelationships.addRelation(cls, BooleanGraphFieldListImpl.class, "*-booleanlist", HAS_LIST, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
+ GraphRelationships.addRelation(cls, HtmlGraphFieldListImpl.class, "*-htmllist", HAS_LIST, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
+ GraphRelationships.addRelation(cls, NodeGraphFieldListImpl.class, "*-nodelist", HAS_LIST, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
+ GraphRelationships.addRelation(cls, MicronodeGraphFieldListImpl.class, "*-micronodelist", HAS_LIST, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
+ }
+
/**
* Return the parent node of the field container.
*
diff --git a/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/container/impl/NodeGraphFieldContainerImpl.java b/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/container/impl/NodeGraphFieldContainerImpl.java
index b3d14e3b63..5268733f17 100644
--- a/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/container/impl/NodeGraphFieldContainerImpl.java
+++ b/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/container/impl/NodeGraphFieldContainerImpl.java
@@ -26,8 +26,6 @@
import java.util.Set;
import java.util.stream.Collectors;
-import org.apache.commons.lang3.StringUtils;
-
import com.gentics.madl.index.IndexHandler;
import com.gentics.madl.type.TypeHandler;
import com.gentics.mesh.context.BulkActionContext;
@@ -37,31 +35,22 @@
import com.gentics.mesh.core.data.HibNodeFieldContainer;
import com.gentics.mesh.core.data.HibNodeFieldContainerEdge;
import com.gentics.mesh.core.data.NodeGraphFieldContainer;
-import com.gentics.mesh.core.data.binary.impl.BinaryImpl;
import com.gentics.mesh.core.data.branch.HibBranch;
import com.gentics.mesh.core.data.dao.ContentDao;
import com.gentics.mesh.core.data.generic.MeshVertexImpl;
import com.gentics.mesh.core.data.impl.GraphFieldContainerEdgeImpl;
import com.gentics.mesh.core.data.node.field.BinaryGraphField;
-import com.gentics.mesh.core.data.node.field.GraphField;
import com.gentics.mesh.core.data.node.field.S3BinaryGraphField;
import com.gentics.mesh.core.data.node.field.StringGraphField;
import com.gentics.mesh.core.data.node.field.impl.BinaryGraphFieldImpl;
import com.gentics.mesh.core.data.node.field.impl.MicronodeGraphFieldImpl;
import com.gentics.mesh.core.data.node.field.impl.S3BinaryGraphFieldImpl;
import com.gentics.mesh.core.data.node.field.list.HibMicronodeFieldList;
-import com.gentics.mesh.core.data.node.field.list.impl.BooleanGraphFieldListImpl;
-import com.gentics.mesh.core.data.node.field.list.impl.HtmlGraphFieldListImpl;
import com.gentics.mesh.core.data.node.field.list.impl.MicronodeGraphFieldListImpl;
-import com.gentics.mesh.core.data.node.field.list.impl.NodeGraphFieldListImpl;
-import com.gentics.mesh.core.data.node.field.list.impl.NumberGraphFieldListImpl;
-import com.gentics.mesh.core.data.node.field.list.impl.StringGraphFieldListImpl;
import com.gentics.mesh.core.data.node.field.nesting.HibMicronodeField;
import com.gentics.mesh.core.data.node.field.nesting.MicronodeGraphField;
-import com.gentics.mesh.core.data.node.impl.MicronodeImpl;
import com.gentics.mesh.core.data.node.impl.NodeImpl;
import com.gentics.mesh.core.data.relationship.GraphRelationships;
-import com.gentics.mesh.core.data.s3binary.impl.S3BinaryImpl;
import com.gentics.mesh.core.data.schema.HibFieldSchemaVersionElement;
import com.gentics.mesh.core.data.schema.HibSchemaVersion;
import com.gentics.mesh.core.data.schema.impl.SchemaContainerVersionImpl;
@@ -113,15 +102,7 @@ public static void init(TypeHandler type, IndexHandler index) {
.withType(NOTUNIQUE)
.withPostfix("bucket"));
- GraphRelationships.addRelation(NodeGraphFieldContainerImpl.class, MicronodeImpl.class, "*", HAS_FIELD, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
- GraphRelationships.addRelation(NodeGraphFieldContainerImpl.class, BinaryImpl.class, "*", HAS_FIELD, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
- GraphRelationships.addRelation(NodeGraphFieldContainerImpl.class, S3BinaryImpl.class, "*", HAS_FIELD, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
- GraphRelationships.addRelation(NodeGraphFieldContainerImpl.class, StringGraphFieldListImpl.class, "*", HAS_LIST, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
- GraphRelationships.addRelation(NodeGraphFieldContainerImpl.class, NumberGraphFieldListImpl.class, "*", HAS_LIST, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
- GraphRelationships.addRelation(NodeGraphFieldContainerImpl.class, BooleanGraphFieldListImpl.class, "*", HAS_LIST, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
- GraphRelationships.addRelation(NodeGraphFieldContainerImpl.class, HtmlGraphFieldListImpl.class, "*", HAS_LIST, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
- GraphRelationships.addRelation(NodeGraphFieldContainerImpl.class, NodeGraphFieldListImpl.class, "*", HAS_LIST, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
- GraphRelationships.addRelation(NodeGraphFieldContainerImpl.class, MicronodeGraphFieldListImpl.class, "*", HAS_LIST, GraphField.FIELD_KEY_PROPERTY_KEY, StringUtils.EMPTY);
+ AbstractGraphFieldContainerImpl.init(type, index, NodeGraphFieldContainerImpl.class);
}
@Override
diff --git a/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/generic/MeshVertexImpl.java b/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/generic/MeshVertexImpl.java
index f696e49630..8a6dc1b2fc 100644
--- a/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/generic/MeshVertexImpl.java
+++ b/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/generic/MeshVertexImpl.java
@@ -55,6 +55,7 @@
import com.gentics.mesh.core.data.relationship.GraphRelationship;
import com.gentics.mesh.core.data.relationship.GraphRelationships;
import com.gentics.mesh.core.data.role.HibRole;
+import com.gentics.mesh.core.data.schema.HibMicroschema;
import com.gentics.mesh.core.data.schema.HibSchema;
import com.gentics.mesh.core.data.schema.impl.SchemaContainerImpl;
import com.gentics.mesh.core.data.schema.impl.SchemaContainerVersionImpl;
@@ -260,25 +261,47 @@ protected S mapSorting(S sorting) {
sorting.clearSort();
items.entrySet().stream().forEach(entry -> {
String key = mapGraphQlFieldNameForSorting(entry.getKey());
- String[] keyParts = key.split("\\.");
- if (keyParts.length > 1) {
- // We expect format of 'fields.'.
- if ("fields".equals(keyParts[0])) {
- if (keyParts.length > 2) {
- HibSchema schema = Tx.get().schemaDao().findByName(keyParts[1]);
- if (schema == null) {
- throw new IllegalArgumentException("No schema found for sorting request: " + key);
+ String[] fieldParts = key.split("fields\\.");
+ String newKey = StringUtils.EMPTY;
+ if (fieldParts.length > 1) {
+ for (int i = 0 ; i < fieldParts.length; i++) {
+ String part = fieldParts[i];
+ String[] keyParts = part.split("\\.");
+ if (keyParts.length > 1) {
+ HibSchema schema = Tx.get().schemaDao().findByName(keyParts[0]);
+ String type;
+ if (schema != null) {
+ FieldSchema field = schema.getLatestVersion().getSchema().getFieldsAsMap().get(keyParts[1]);
+ if (field == null) {
+ throw new IllegalArgumentException("No field found for sorting request: " + key);
+ }
+ type = field.getType().toLowerCase();
+ } else {
+ HibMicroschema microschema = Tx.get().microschemaDao().findByName(keyParts[0]);
+ if (microschema != null) {
+ //
+ FieldSchema field = microschema.getLatestVersion().getSchema().getFieldsAsMap().get(keyParts[1]);
+ if (field == null) {
+ throw new IllegalArgumentException("No field found for sorting request: " + key);
+ }
+ type = field.getType().toLowerCase();
+ } else {
+ throw new IllegalArgumentException("No schema found for sorting request: " + key);
+ }
+ }
+ if (i > 0 && newKey.length() > 0) {
+ newKey += ".";
}
- FieldSchema field = schema.getLatestVersion().getSchema().getFieldsAsMap().get(keyParts[2]);
- if (field == null) {
- throw new IllegalArgumentException("No field found for sorting request: " + key);
+ newKey += "fields." + keyParts[0] + "." + keyParts[1] + "-" + type;
+ if (keyParts.length > 2) {
+ newKey += Arrays.stream(keyParts).skip(2).map(this::mapGraphQlFieldNameForSorting).collect(Collectors.joining(".", ".", StringUtils.EMPTY));
}
- key = keyParts[0] + "." + keyParts[2] + "-" + field.getType().toLowerCase();
}
- // else process as non-schema content field
}
+ } else {
+ newKey = key;
}
- sorting.putSort(key, entry.getValue());
+ sorting.putSort(newKey, entry.getValue());
});
return sorting;
}
diff --git a/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/impl/TagFamilyImpl.java b/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/impl/TagFamilyImpl.java
index ad16aa6f25..87a32ab528 100644
--- a/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/impl/TagFamilyImpl.java
+++ b/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/impl/TagFamilyImpl.java
@@ -233,7 +233,7 @@ public Page extends Tag> findAll(InternalActionContext ac, PagingParameters pa
PagingParameters sorting = mapSorting(pagingInfo);
Optional maybeParsedFilter = maybeExtraFilter
.map(extraFilter -> parseFilter(extraFilter, ContainerType.PUBLISHED, ac.getUser(), READ_PERM, Optional.empty()))
- .or(() -> permissionFilter(ac.getUser(), READ_PERM, Optional.empty(), Optional.empty()));
+ .or(() -> permissionFilterIfRequired(pagingInfo, ac.getUser(), READ_PERM, Optional.empty(), Optional.empty()));
Stream extends Tag> stream = toStream(db().getVertices(
getPersistanceClass(),
new String[] {},
diff --git a/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/node/impl/MicronodeImpl.java b/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/node/impl/MicronodeImpl.java
index 0144653fd2..1918bf8900 100644
--- a/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/node/impl/MicronodeImpl.java
+++ b/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/node/impl/MicronodeImpl.java
@@ -20,6 +20,7 @@
import com.gentics.mesh.core.data.node.HibNode;
import com.gentics.mesh.core.data.node.Micronode;
import com.gentics.mesh.core.data.node.field.list.HibMicronodeFieldList;
+import com.gentics.mesh.core.data.relationship.GraphRelationships;
import com.gentics.mesh.core.data.schema.HibFieldSchemaVersionElement;
import com.gentics.mesh.core.data.schema.HibMicroschemaVersion;
import com.gentics.mesh.core.rest.common.FieldTypes;
@@ -54,6 +55,11 @@ public static void init(TypeHandler type, IndexHandler index) {
.withField(MICROSCHEMA_VERSION_KEY_PROPERTY, FieldType.STRING));
index.createIndex(VertexIndexDefinition.vertexIndex(MicronodeImpl.class)
.withField(MICROSCHEMA_VERSION_KEY_PROPERTY, FieldType.STRING));
+
+ GraphRelationships.addUnmappedRelation(MicronodeImpl.class, MicronodeImpl.class, "micronode");
+ GraphRelationships.addUnmappedRelation(MicronodeImpl.class, MicronodeImpl.class, "fields");
+
+ AbstractGraphFieldContainerImpl.init(type, index, MicronodeImpl.class);
}
@Override
diff --git a/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/node/impl/NodeImpl.java b/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/node/impl/NodeImpl.java
index 73afb9940c..7388bc3b8e 100644
--- a/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/node/impl/NodeImpl.java
+++ b/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/node/impl/NodeImpl.java
@@ -139,6 +139,7 @@ public static void init(TypeHandler type, IndexHandler index) {
.withPostfix("branch_parents")
.withField(BRANCH_PARENTS_KEY_PROPERTY, STRING_SET));
+ GraphRelationships.addUnmappedRelation(NodeImpl.class, NodeImpl.class, "node");
GraphRelationships.addRelation(NodeImpl.class, NodeGraphFieldContainerImpl.class, "fields", HAS_FIELD_CONTAINER, "edgeType", ContainerType.INITIAL.getCode());
GraphRelationships.addRelation(NodeImpl.class, SchemaContainerImpl.class, "schema");
GraphRelationships.addRelation(NodeImpl.class, UserImpl.class, "creator");
@@ -246,7 +247,6 @@ public Result getChildren() {
new Object[] { getUuid() }), NodeImpl.class));
}
- @Override
public Result getChildren(String branchUuid, ContainerType containerType, PagingParameters sorting, Optional> maybeFilter, Optional maybeUser) {
InternalPermission perm = containerType == PUBLISHED ? READ_PUBLISHED_PERM : READ_PERM;
Tx tx = GraphDBTx.getGraphTx();
diff --git a/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/root/impl/AbstractRootVertex.java b/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/root/impl/AbstractRootVertex.java
index 47f45b5b24..860974e97c 100644
--- a/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/root/impl/AbstractRootVertex.java
+++ b/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/root/impl/AbstractRootVertex.java
@@ -192,7 +192,7 @@ protected Page extends T> findAll(InternalActionContext ac, PagingParameters p
PagingParameters sorting = mapSorting(pagingInfo);
Optional maybeParsedFilter = maybeExtraFilter
.map(extraFilter -> parseFilter(extraFilter, ctype, ac.getUser(), perm, Optional.empty()))
- .or(() -> permissionFilter(ac.getUser(), perm, Optional.empty(), Optional.of(ctype)));
+ .or(() -> permissionFilterIfRequired(pagingInfo, ac.getUser(), perm, Optional.empty(), Optional.of(ctype)));
Stream extends T> stream = toStream(db().getVertices(
getPersistanceClass(),
new String[] {},
diff --git a/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/root/impl/NodeRootImpl.java b/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/root/impl/NodeRootImpl.java
index 6f2e8744c7..71ded46cfb 100644
--- a/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/root/impl/NodeRootImpl.java
+++ b/mdm/orientdb-wrapper/src/main/java/com/gentics/mesh/core/data/root/impl/NodeRootImpl.java
@@ -32,6 +32,7 @@
import com.gentics.mesh.core.data.impl.GraphFieldContainerEdgeImpl;
import com.gentics.mesh.core.data.impl.ProjectImpl;
import com.gentics.mesh.core.data.node.Node;
+import com.gentics.mesh.core.data.node.field.BinaryGraphField;
import com.gentics.mesh.core.data.node.impl.NodeImpl;
import com.gentics.mesh.core.data.page.Page;
import com.gentics.mesh.core.data.page.impl.DynamicTransformableStreamPageImpl;
@@ -146,6 +147,7 @@ private Stream findAll(HibUser user, InternalPermission perm, String pro
maybeContainerType,
maybeFilter
.map(f -> parseFilter(f, maybeContainerType.orElse(PUBLISHED), user, perm, Optional.empty()))
+ .or(() -> permissionFilterIfRequired(paging, user, perm, Optional.empty(), maybeContainerType))
));
}
@@ -208,6 +210,9 @@ public String mapGraphQlFieldNameForSorting(String gqlName) {
switch (gqlName) {
case "edited": return "fields.last_edited_timestamp";
case "editor": return "fields.editor";
+ case "fileName": return BinaryGraphField.BINARY_FILENAME_PROPERTY_KEY;
+ case "imageDominantColor": return BinaryGraphField.BINARY_IMAGE_DOMINANT_COLOR_PROPERTY_KEY;
+ case "mimeType": return BinaryGraphField.BINARY_CONTENT_TYPE_PROPERTY_KEY;
}
return super.mapGraphQlFieldNameForSorting(gqlName);
}
diff --git a/tests/common/src/main/java/com/gentics/mesh/assertj/impl/JsonObjectAssert.java b/tests/common/src/main/java/com/gentics/mesh/assertj/impl/JsonObjectAssert.java
index 84a31efd63..e335de744b 100644
--- a/tests/common/src/main/java/com/gentics/mesh/assertj/impl/JsonObjectAssert.java
+++ b/tests/common/src/main/java/com/gentics/mesh/assertj/impl/JsonObjectAssert.java
@@ -226,6 +226,8 @@ public JsonObjectAssert compliesTo(String assertion, String msg, Integer lineNr)
pathIsDate(path, msg);
} else if ("".equals(value)) {
pathIsUndefined(path, msg);
+ } else if ("".equals(value)) {
+ pathIsEmpty(path, msg);
} else {
has(path, replaceVariables(value), msg);
}
@@ -262,6 +264,21 @@ public JsonObjectAssert pathIsUndefined(String path, String msg) {
return this;
}
+ @SuppressWarnings("rawtypes")
+ private JsonObjectAssert pathIsEmpty(String path, String msg) {
+ try {
+ Object value = JsonPath.read(actual.toString(), path);
+ if (value instanceof Map && ((Map) value).size() > 0) {
+ fail(msg + " The value at path {" + path + "} is not empty, while should be.");
+ } else if (value instanceof Collection && ((Collection) value).size() > 0) {
+ fail(msg + " The value at path {" + path + "} is not empty, while should be.");
+ }
+ } catch (PathNotFoundException e) {
+ fail(msg + " The value at path {" + path + "} was not present but it should be present but empty.");
+ }
+ return this;
+ }
+
/**
* Assert that the string value which is present at the given path matches the pattern of a uuid.
*
diff --git a/tests/tests-core/src/main/java/com/gentics/mesh/core/graphql/GraphQLEndpointTest.java b/tests/tests-core/src/main/java/com/gentics/mesh/core/graphql/GraphQLEndpointTest.java
index ebd8327365..9302af8d81 100644
--- a/tests/tests-core/src/main/java/com/gentics/mesh/core/graphql/GraphQLEndpointTest.java
+++ b/tests/tests-core/src/main/java/com/gentics/mesh/core/graphql/GraphQLEndpointTest.java
@@ -212,7 +212,10 @@ protected static Stream> queries() {
Arrays.asList("filtering/nodes-binary-field-native", true, false, "draft"),
Arrays.asList("filtering/nodes-s3binary-field-native", true, false, "draft"),
Arrays.asList("filtering/nodes-nodelist-field-native", true, false, "draft"),
- Arrays.asList("filtering/nodes-micronodelist-field-native", true, false, "draft")
+ Arrays.asList("filtering/nodes-micronodelist-field-native", true, false, "draft"),
+ Arrays.asList("filtering/nodes-sorted-micronode", true, false, "draft"),
+ Arrays.asList("filtering/nodes-sorted-binary", true, false, "draft"),
+ Arrays.asList("filtering/nodes-sorted-node-field", true, false, "draft")
);
}
@@ -412,7 +415,7 @@ public void testNodeQuery() throws Exception {
HibBinary binary = tx.binaries().create("hashsumvalue", 1L).runInExistingTx(tx);
binary.setImageHeight(10).setImageWidth(20).setSize(2048);
container.createBinary("binary", binary).setImageDominantColor("00FF00")
- .setImageFocalPoint(new FocalPoint(0.2f, 0.3f)).setMimeType("image/jpeg");
+ .setImageFocalPoint(new FocalPoint(0.2f, 0.3f)).setMimeType("image/jpeg").setFileName("some_image.jpg");
// s3binary
S3HibBinary s3binary = tx.s3binaries().create(UUIDUtil.randomUUID(), node.getUuid() + "/s3", "test.jpg").runInExistingTx(tx);
@@ -477,6 +480,30 @@ public void testNodeQuery() throws Exception {
micronodeField.getMicronode().createString("lastName").setString("Doe");
micronodeField.getMicronode().createString("address").setString("Somewhere");
micronodeField.getMicronode().createString("postcode").setString("1010");
+
+ // Second micronode
+ HibNodeFieldContainer container3 = tx.contentDao().createFieldContainer(node3, "en", initialBranch(), user());
+ // micronodeList
+ micronodeList = container3.createMicronodeList("micronodeList");
+ firstMicronode = micronodeList.createMicronode(microschemaContainer("vcard").getLatestVersion());
+ firstMicronode.createString("firstName").setString("Jane");
+ firstMicronode.createString("lastName").setString("Dow");
+ firstMicronode.createString("address").setString("Overthere");
+ firstMicronode.createString("postcode").setString("8010");
+
+ secondMicronode = micronodeList.createMicronode(microschemaDao.findByUuid(microschemaUuid).getLatestVersion());
+ secondMicronode.createString("text").setString("Jane");
+ secondMicronode.createNode("nodeRef", content());
+ micrnodeNodeList = secondMicronode.createNodeList("nodeList");
+ micrnodeNodeList.createNode(0, node2);
+ micrnodeNodeList.createNode(1, node3);
+
+ // micronode
+ micronodeField = container3.createMicronode("micronode", microschemaContainer("vcard").getLatestVersion());
+ micronodeField.getMicronode().createString("firstName").setString("Jane");
+ micronodeField.getMicronode().createString("lastName").setString("Dow");
+ micronodeField.getMicronode().createString("address").setString("Overthere");
+ micronodeField.getMicronode().createString("postcode").setString("8010");
}
tx.contentDao().updateWebrootPathInfo(container, initialBranchUuid(), null);
tx.success();
@@ -539,7 +566,7 @@ public void testNodeQuery() throws Exception {
assertion.accept(jsonResponse);
}
} catch (Throwable e) {
- getTestContext().LOG.error("Assertion failed for: \n{}\nPayload:\n{}", query, response.toJson());
+ getTestContext().LOG.error("Assertion failed for: \n{}\nPayload:\n{}", query, jsonResponse.encodePrettily());
throw e;
}
}
diff --git a/tests/tests-core/src/main/java/com/gentics/mesh/core/language/LanguageEndpointTest.java b/tests/tests-core/src/main/java/com/gentics/mesh/core/language/LanguageEndpointTest.java
index 249985c681..8b73564a9a 100644
--- a/tests/tests-core/src/main/java/com/gentics/mesh/core/language/LanguageEndpointTest.java
+++ b/tests/tests-core/src/main/java/com/gentics/mesh/core/language/LanguageEndpointTest.java
@@ -16,6 +16,7 @@
import com.gentics.mesh.FieldUtil;
import com.gentics.mesh.core.data.perm.InternalPermission;
+import com.gentics.mesh.core.rest.SortOrder;
import com.gentics.mesh.core.rest.error.GenericRestException;
import com.gentics.mesh.core.rest.lang.LanguageListResponse;
import com.gentics.mesh.core.rest.lang.LanguageResponse;
@@ -26,6 +27,7 @@
import com.gentics.mesh.parameter.client.GenericParametersImpl;
import com.gentics.mesh.parameter.impl.NodeParametersImpl;
import com.gentics.mesh.parameter.impl.ProjectLoadParametersImpl;
+import com.gentics.mesh.parameter.impl.SortingParametersImpl;
import com.gentics.mesh.test.MeshTestSetting;
import com.gentics.mesh.test.TestSize;
import com.gentics.mesh.test.context.AbstractMeshTest;
@@ -369,9 +371,11 @@ public void testNotPermittedProject() {
}
}
- @Override
@Test
- @Ignore
+ @Override
public void testReadPermittedSorted() throws Exception {
+ LanguageListResponse list = call(() -> client().findLanguages(new SortingParametersImpl("name", SortOrder.DESCENDING)));
+ assertEquals("Total data size should be 11", 11, list.getData().size());
+ assertThat(list.getData()).isSortedAccordingTo((a, b) -> b.getName().compareTo(a.getName()));
}
}
diff --git a/tests/tests-core/src/main/resources/graphql/filtering/nodes-micronode-field-native b/tests/tests-core/src/main/resources/graphql/filtering/nodes-micronode-field-native
index 0054e31ea0..58dc9db4d5 100644
--- a/tests/tests-core/src/main/resources/graphql/filtering/nodes-micronode-field-native
+++ b/tests/tests-core/src/main/resources/graphql/filtering/nodes-micronode-field-native
@@ -24,7 +24,7 @@
}
}
}) {
- # [$.data.micronodeIsNull.elements.length()=8]
+ # [$.data.micronodeIsNull.elements.length()=7]
elements {
uuid
schema {
diff --git a/tests/tests-core/src/main/resources/graphql/filtering/nodes-micronodelist-field-native b/tests/tests-core/src/main/resources/graphql/filtering/nodes-micronodelist-field-native
index 52dd8496ab..3af939abf1 100644
--- a/tests/tests-core/src/main/resources/graphql/filtering/nodes-micronodelist-field-native
+++ b/tests/tests-core/src/main/resources/graphql/filtering/nodes-micronodelist-field-native
@@ -66,7 +66,7 @@
}
}
}) {
- # [$.data.noneMatch.elements.length()=0]
+ # [$.data.noneMatch.elements.length()=1]
elements {
uuid
schema {
@@ -91,7 +91,7 @@
}
}
}) {
- # [$.data.anyNotMatch.elements.length()=1]
+ # [$.data.anyNotMatch.elements.length()=2]
elements {
uuid
schema {
diff --git a/tests/tests-core/src/main/resources/graphql/filtering/nodes-nodereferences-java b/tests/tests-core/src/main/resources/graphql/filtering/nodes-nodereferences-java
index 2ceb2bf77d..94870c9fc1 100644
--- a/tests/tests-core/src/main/resources/graphql/filtering/nodes-nodereferences-java
+++ b/tests/tests-core/src/main/resources/graphql/filtering/nodes-nodereferences-java
@@ -83,7 +83,7 @@
count: { gt: 1 }
}
}) {
- # [$.data.hasMicronodeReferences.elements.length()=1]
+ # [$.data.hasMicronodeReferences.elements.length()=2]
elements {
uuid
schema {
@@ -96,7 +96,7 @@
count: { gt: 2 }
}
}) {
- # [$.data.moreThan2References.elements.length()=2]
+ # [$.data.moreThan2References.elements.length()=3]
elements {
uuid
schema {
diff --git a/tests/tests-core/src/main/resources/graphql/filtering/nodes-nodereferences-native b/tests/tests-core/src/main/resources/graphql/filtering/nodes-nodereferences-native
index 9406069125..557f5dd349 100644
--- a/tests/tests-core/src/main/resources/graphql/filtering/nodes-nodereferences-native
+++ b/tests/tests-core/src/main/resources/graphql/filtering/nodes-nodereferences-native
@@ -97,7 +97,7 @@
count: { gt: 1 }
}
}) {
- # [$.data.hasMicronodeReferences.elements.length()=1]
+ # [$.data.hasMicronodeReferences.elements.length()=2]
elements {
uuid
schema {
@@ -110,7 +110,7 @@
count: { gt: 2 }
}
}) {
- # [$.data.moreThan2References.elements.length()=2]
+ # [$.data.moreThan2References.elements.length()=3]
elements {
uuid
schema {
diff --git a/tests/tests-core/src/main/resources/graphql/filtering/nodes-s3binary-field-native b/tests/tests-core/src/main/resources/graphql/filtering/nodes-s3binary-field-native
index 700fba56cc..42e931b7fe 100644
--- a/tests/tests-core/src/main/resources/graphql/filtering/nodes-s3binary-field-native
+++ b/tests/tests-core/src/main/resources/graphql/filtering/nodes-s3binary-field-native
@@ -20,7 +20,7 @@
schema: {is: folder}
fields: {
folder: {
- s3Binary: {s3binary:{key: { like: "%/s3" }}}
+ s3Binary: {s3binary:{s3ObjectKey: { like: "%/s3" }}}
}
}
}) {
diff --git a/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-binary b/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-binary
new file mode 100644
index 0000000000..a0ee48c5da
--- /dev/null
+++ b/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-binary
@@ -0,0 +1,40 @@
+{
+ nodes(filter: {
+ schema: {is: folder}
+ }
+ sort: {
+ fields: {
+ folder: {
+ binary: {
+ fileName: DESCENDING
+ }
+ }
+ }
+ }
+ ) {
+ # [$.data.nodes.elements.length()=9]
+ elements {
+ uuid
+ schema {
+ name
+ }
+ ... on folder {
+ fields {
+ binary {
+ # [$.data.nodes.elements[0].fields.binary=]
+ # [$.data.nodes.elements[1].fields.binary=]
+ # [$.data.nodes.elements[2].fields.binary=]
+ # [$.data.nodes.elements[3].fields.binary=]
+ # [$.data.nodes.elements[4].fields.binary=]
+ # [$.data.nodes.elements[5].fields.binary=]
+ # [$.data.nodes.elements[6].fields.binary=]
+ # [$.data.nodes.elements[7].fields.binary=]
+ # [$.data.nodes.elements[8].fields.binary.fileName=some_image.jpg]
+ fileName
+ }
+ }
+ }
+ }
+ }
+}
+# [$.errors=]
\ No newline at end of file
diff --git a/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-binary.v1 b/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-binary.v1
new file mode 100644
index 0000000000..b35de08493
--- /dev/null
+++ b/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-binary.v1
@@ -0,0 +1,40 @@
+{
+ nodes(filter: {
+ schema: {is: folder}
+ }
+ sort: {
+ fields: {
+ folder: {
+ binary: {
+ fileName: DESCENDING
+ }
+ }
+ }
+ }
+ ) {
+ # [$.data.nodes.elements.length()=9]
+ elements {
+ uuid
+ schema {
+ name
+ }
+ fields {
+ ... on folder {
+ binary {
+ # [$.data.nodes.elements[0].fields.binary=]
+ # [$.data.nodes.elements[1].fields.binary=]
+ # [$.data.nodes.elements[2].fields.binary=]
+ # [$.data.nodes.elements[3].fields.binary=]
+ # [$.data.nodes.elements[4].fields.binary=]
+ # [$.data.nodes.elements[5].fields.binary=]
+ # [$.data.nodes.elements[6].fields.binary=]
+ # [$.data.nodes.elements[7].fields.binary=]
+ # [$.data.nodes.elements[8].fields.binary.fileName=some_image.jpg]
+ fileName
+ }
+ }
+ }
+ }
+ }
+}
+# [$.errors=]
\ No newline at end of file
diff --git a/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-micronode b/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-micronode
new file mode 100644
index 0000000000..fcace1b664
--- /dev/null
+++ b/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-micronode
@@ -0,0 +1,48 @@
+{
+ nodes(filter: {
+ schema: {is: folder}
+ fields: {
+ folder: {
+ micronode: {micronode: {microschema: {is: vcard} }}
+ }
+ }
+ }
+ sort: {
+ fields: {
+ folder: {
+ micronode: {
+ micronode: {
+ fields: {
+ vcard: {
+ address: DESCENDING
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ) {
+ # [$.data.nodes.elements.length()=2]
+ # [$.data.nodes.elements[0].fields.micronode.fields.address=Somewhere]
+ # [$.data.nodes.elements[1].fields.micronode.fields.address=Overthere]
+ elements {
+ uuid
+ schema {
+ name
+ }
+ ... on folder {
+ fields {
+ micronode {
+ ... on vcard {
+ fields {
+ address
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+# [$.errors=]
\ No newline at end of file
diff --git a/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-micronode.v1 b/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-micronode.v1
new file mode 100644
index 0000000000..9a9d5c3b0d
--- /dev/null
+++ b/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-micronode.v1
@@ -0,0 +1,46 @@
+{
+ nodes(filter: {
+ schema: {is: folder}
+ fields: {
+ folder: {
+ micronode: {micronode: {microschema: {is: vcard} }}
+ }
+ }
+ }
+ sort: {
+ fields: {
+ folder: {
+ micronode: {
+ micronode: {
+ fields: {
+ vcard: {
+ address: DESCENDING
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ) {
+ # [$.data.nodes.elements.length()=2]
+ # [$.data.nodes.elements[0].fields.micronode.address=Somewhere]
+ # [$.data.nodes.elements[1].fields.micronode.address=Overthere]
+ elements {
+ uuid
+ schema {
+ name
+ }
+ fields {
+ ... on folder {
+ micronode {
+ ... on vcard {
+ address
+ }
+ }
+ }
+ }
+ }
+ }
+}
+# [$.errors=]
\ No newline at end of file
diff --git a/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-node-field b/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-node-field
new file mode 100644
index 0000000000..ece5d3139a
--- /dev/null
+++ b/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-node-field
@@ -0,0 +1,65 @@
+{
+ nodeRefSlugLike: nodes(
+ filter: {
+ schema: {is: folder}
+ fields: {
+ folder: {
+ nodeRef: {node: {schema: {is: content} fields: { content: { slug: { like: "%.html" } } }}}
+ }
+ }
+ }
+ sort: {
+ fields: {
+ folder: {
+ nodeRef: {node: { fields: { content: { slug: ASCENDING } }}}
+ }
+ }
+ }
+ ) {
+ # [$.data.nodeRefSlugLike.elements.length()=2]
+ elements {
+ uuid
+ schema {
+ name
+ }
+ }
+ }
+
+ nodeRefIsNotNull: nodes(
+ filter: {
+ schema: {is: folder}
+ fields: {
+ folder: {
+ nodeRef: {isNull:false}
+ }
+ }
+ }
+ sort: {
+ fields: {
+ folder: {
+ nodeRef: {node: { fields: { content: { slug: ASCENDING } }}}
+ }
+ }
+ }
+ ) {
+ # [$.data.nodeRefIsNotNull.elements.length()=3]
+ # [$.data.nodeRefIsNotNull.elements[0].fields.nodeRef=]
+ # [$.data.nodeRefIsNotNull.elements[1].fields.nodeRef.fields.slug=News Overview.en.html]
+ # [$.data.nodeRefIsNotNull.elements[2].fields.nodeRef.fields.slug=News Overview.en.html]
+ elements {
+ uuid
+ ... on folder {
+ fields {
+ nodeRef {
+ ... on content {
+ fields {
+ slug
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+# [$.errors=]
\ No newline at end of file
diff --git a/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-node-field.v1 b/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-node-field.v1
new file mode 100644
index 0000000000..5bcc0a60c1
--- /dev/null
+++ b/tests/tests-core/src/main/resources/graphql/filtering/nodes-sorted-node-field.v1
@@ -0,0 +1,65 @@
+{
+ nodeRefSlugLike: nodes(
+ filter: {
+ schema: {is: folder}
+ fields: {
+ folder: {
+ nodeRef: {node: {schema: {is: content} fields: { content: { slug: { like: "%.html" } } }}}
+ }
+ }
+ }
+ sort: {
+ fields: {
+ folder: {
+ nodeRef: {node: { fields: { content: { slug: ASCENDING } }}}
+ }
+ }
+ }
+ ) {
+ # [$.data.nodeRefSlugLike.elements.length()=2]
+ elements {
+ uuid
+ schema {
+ name
+ }
+ }
+ }
+
+ nodeRefIsNotNull: nodes(
+ filter: {
+ schema: {is: folder}
+ fields: {
+ folder: {
+ nodeRef: {isNull:false}
+ }
+ }
+ }
+ sort: {
+ fields: {
+ folder: {
+ nodeRef: {node: { fields: { content: { slug: ASCENDING } }}}
+ }
+ }
+ }
+ ) {
+ # [$.data.nodeRefIsNotNull.elements.length()=3]
+ # [$.data.nodeRefIsNotNull.elements[0].fields.nodeRef.fields=]
+ # [$.data.nodeRefIsNotNull.elements[1].fields.nodeRef.fields.slug=News Overview.en.html]
+ # [$.data.nodeRefIsNotNull.elements[2].fields.nodeRef.fields.slug=News Overview.en.html]
+ elements {
+ uuid
+ fields {
+ ... on folder {
+ nodeRef {
+ fields {
+ ... on content {
+ slug
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+# [$.errors=]
\ No newline at end of file
diff --git a/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/BinaryFieldFilter.java b/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/BinaryFieldFilter.java
index 165a656b28..bb51a9a99b 100644
--- a/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/BinaryFieldFilter.java
+++ b/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/BinaryFieldFilter.java
@@ -44,8 +44,8 @@ private BinaryFieldFilter(String owner, GraphQLContext context) {
@Override
protected List> getFilters() {
List> filters = super.getFilters();
- filters.add(makeWrappedFieldFilter("filename", "Filters by filename", StringFilter.filter(), HibImageDataField::getFileName));
- filters.add(makeWrappedFieldFilter("mime", "Filters by MIME type", StringFilter.filter(), HibImageDataField::getMimeType));
+ filters.add(makeWrappedFieldFilter("fileName", "Filters by filename", StringFilter.filter(), HibImageDataField::getFileName));
+ filters.add(makeWrappedFieldFilter("mimeType", "Filters by MIME type", StringFilter.filter(), HibImageDataField::getMimeType));
filters.add(new MappedFilter<>(owner, "variants", "Filters by image variants",
ListFilter.imageVariantListFilter(context, "BINARYFIELD"),
content -> content == null ? null : (Collection) CommonTx.get().imageVariantDao().getVariants(content, context).list(), Pair.pair("variants", new JoinPart("IMAGEVARIANT", "uuid"))));
diff --git a/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/BinaryFilter.java b/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/BinaryFilter.java
index e12a799887..f706f646a0 100644
--- a/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/BinaryFilter.java
+++ b/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/BinaryFilter.java
@@ -43,11 +43,8 @@ private BinaryFilter(String name, String description, GraphQLContext context) {
@Override
public List> getFilters() {
List> filters = super.getFilters();
- filters.add(new MappedFilter<>(owner, "checksum", "Filters by SHA512 checksum", StringFilter.filter(),
+ filters.add(new MappedFilter<>(owner, "sha512sum", "Filters by SHA512 checksum", StringFilter.filter(),
content -> content == null ? null : content.getSHA512Sum()));
-// filters.add(new MappedFilter<>(owner, "variants", "Filters by image variants",
-// ListFilter.imageVariantListFilter(context, "BINARY"),
-// content -> content == null ? null : (Collection) CommonTx.get().binaryDao().getVariants(content, context).list(), Pair.pair("variants", new JoinPart("IMAGEVARIANT", "value"))));
return filters;
}
}
diff --git a/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/EntityReferenceFilter.java b/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/EntityReferenceFilter.java
index 3387c78f16..cb56782e96 100644
--- a/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/EntityReferenceFilter.java
+++ b/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/EntityReferenceFilter.java
@@ -28,7 +28,6 @@
import com.gentics.mesh.core.data.node.field.nesting.HibMicronodeField;
import com.gentics.mesh.core.data.node.field.nesting.HibNodeField;
import com.gentics.mesh.core.data.node.field.nesting.HibReferenceField;
-import com.gentics.mesh.core.db.CommonTx;
import com.gentics.mesh.core.db.Tx;
import com.gentics.mesh.core.rest.common.ContainerType;
import com.gentics.mesh.graphql.context.GraphQLContext;
@@ -62,17 +61,17 @@ public EntityReferenceFilter(String name, String description, String entityType,
List> filters = new ArrayList<>();
filters.add(FilterField.create("isNull", "Tests if the value is null", GraphQLBoolean,
query -> value -> query == (value == null),
- Optional.of((query) -> wrapReferencingEdgeFilter("isNull", query, FilterField.isNull() )), false, getOwner()));
+ Optional.of((query) -> wrapReferencingEdgeFilter("isNull", query, FilterField.isNull() )), false, false, getOwner(), Optional.empty()));
filters.add(FilterField.create(referenceType, "Checks if any list item does not match the given predicate", referenceFilter.getType(),
query -> val -> val != null && referenceFilter.createPredicate(query).test(val.getReferencedEntity()),
- Optional.of((query) -> wrapReferencedEntity(query)), true));
+ Optional.of((query) -> wrapReferencedEntity(query)), true, referenceFilter.isSortable(), Optional.empty(), Optional.of(referenceFilter.getSortingType())));
return filters;
}
protected final FilterField makeWrappedFieldFilter(String filterName, String description, Filter edgeTypeFilter, Function mapper) {
return FilterField.create(filterName, description, edgeTypeFilter.getType(),
query -> val -> val != null && edgeTypeFilter.createPredicate(query).test(mapper.apply(val)),
- Optional.of((query) -> wrapReferencingEdgeFilter(filterName, query, edgeTypeFilter)), true, getOwner());
+ Optional.of((query) -> wrapReferencingEdgeFilter(filterName, query, edgeTypeFilter)), true, edgeTypeFilter.isSortable(), getOwner(), Optional.of(edgeTypeFilter.getSortingType()));
}
protected final FilterOperation> wrapReferencingEdgeFilter(String fieldName, FilterQuery, I> query, Filter, I> edgeFilter) {
diff --git a/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/ImageDataFilter.java b/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/ImageDataFilter.java
index 90f9a1b961..151778dd21 100644
--- a/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/ImageDataFilter.java
+++ b/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/ImageDataFilter.java
@@ -42,7 +42,6 @@ protected ImageDataFilter(String name, String description, String owner) {
@Override
public boolean isSortable() {
- // TODO implement later
return false;
}
}
diff --git a/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/S3BinaryFilter.java b/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/S3BinaryFilter.java
index dae1089dde..6d7ac07ca5 100644
--- a/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/S3BinaryFilter.java
+++ b/verticles/graphql/src/main/java/com/gentics/mesh/graphql/filter/S3BinaryFilter.java
@@ -39,9 +39,9 @@ private S3BinaryFilter(String name, String description) {
@Override
public List> getFilters() {
List> filters = super.getFilters();
- filters.add(new MappedFilter<>(owner, "key", "Filters by S3 object key", StringFilter.filter(), content -> content == null ? null : content.getS3ObjectKey()));
- filters.add(new MappedFilter<>(owner, "filename", "Filters by S3 object filename", StringFilter.filter(), content -> content == null ? null : content.getFileName()));
- filters.add(new MappedFilter<>(owner, "mime", "Filters by S3 object MIME type", StringFilter.filter(), content -> content == null ? null : content.getMimeType()));
+ filters.add(new MappedFilter<>(owner, "s3ObjectKey", "Filters by S3 object key", StringFilter.filter(), content -> content == null ? null : content.getS3ObjectKey()));
+ filters.add(new MappedFilter<>(owner, "fileName", "Filters by S3 object filename", StringFilter.filter(), content -> content == null ? null : content.getFileName()));
+ filters.add(new MappedFilter<>(owner, "mimeType", "Filters by S3 object MIME type", StringFilter.filter(), content -> content == null ? null : content.getMimeType()));
return filters;
}
}
\ No newline at end of file