Skip to content

Commit

Permalink
Initial support for MatchPredicates in Device REST API
Browse files Browse the repository at this point in the history
Signed-off-by: Claudio Mezzasalma <claudio.mezzasalma@eurotech.com>
  • Loading branch information
Claudio Mezzasalma committed Aug 5, 2020
1 parent 890e9bd commit e89ce59
Show file tree
Hide file tree
Showing 14 changed files with 281 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*******************************************************************************
* Copyright (c) 2020 Eurotech and/or its affiliates and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eurotech - initial API and implementation
*******************************************************************************/
package org.eclipse.kapua.commons.model.query.predicate;

import java.util.List;

import org.eclipse.kapua.model.query.predicate.MatchPredicate;

/**
* {@link MatchPredicate} implementation.
*
* @since 1.2.0
*/
public class AbstractMatchPredicate<T> implements MatchPredicate<T> {

protected List<String> attributeNames;
protected T matchTerm;

@Override
public List<String> getAttributeNames() {
return attributeNames;
}

@Override
public T getMatchTerm() {
return matchTerm;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016, 2019 Eurotech and/or its affiliates and others
* Copyright (c) 2016, 2020 Eurotech and/or its affiliates and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
Expand All @@ -19,6 +19,8 @@
import org.eclipse.kapua.commons.jpa.EntityManager;
import org.eclipse.kapua.commons.model.AbstractKapuaUpdatableEntity;
import org.eclipse.kapua.commons.model.id.KapuaEid;
import org.eclipse.kapua.commons.model.query.predicate.AttributePredicateImpl;
import org.eclipse.kapua.commons.model.query.predicate.OrPredicateImpl;
import org.eclipse.kapua.commons.security.KapuaSecurityUtils;
import org.eclipse.kapua.commons.security.KapuaSession;
import org.eclipse.kapua.commons.setting.system.SystemSetting;
Expand All @@ -36,6 +38,8 @@
import org.eclipse.kapua.model.query.SortOrder;
import org.eclipse.kapua.model.query.predicate.AndPredicate;
import org.eclipse.kapua.model.query.predicate.AttributePredicate;
import org.eclipse.kapua.model.query.predicate.AttributePredicate.Operator;
import org.eclipse.kapua.model.query.predicate.MatchPredicate;
import org.eclipse.kapua.model.query.predicate.OrPredicate;
import org.eclipse.kapua.model.query.predicate.QueryPredicate;
import org.eclipse.kapua.service.authorization.access.AccessInfo;
Expand Down Expand Up @@ -577,6 +581,13 @@ private static <E> Predicate handleKapuaQueryPredicates(@NotNull QueryPredicate
} else if (queryPredicate instanceof OrPredicate) {
OrPredicate orPredicate = (OrPredicate) queryPredicate;
predicate = handleOrPredicate(orPredicate, binds, cb, userPermissionRoot, entityType);
} else if (queryPredicate instanceof MatchPredicate) {
MatchPredicate<?> matchPredicate = (MatchPredicate<?>) queryPredicate;
OrPredicate orPredicate = new OrPredicateImpl();
for (String attributeName : matchPredicate.getAttributeNames()) {
orPredicate.getPredicates().add(new AttributePredicateImpl<>(attributeName, matchPredicate.getMatchTerm(), Operator.STARTS_WITH_IGNORE_CASE));
}
predicate = handleOrPredicate(orPredicate, binds, cb, userPermissionRoot, entityType);
}
return predicate;
}
Expand Down Expand Up @@ -681,13 +692,27 @@ private static <E> Predicate handleAttributePredicate(@NotNull AttributePredicat
expr = cb.like(extractAttribute(entityRoot, attrName), pl);
break;

case LIKE_IGNORE_CASE:
strAttrValue = attrValue.toString().replace(LIKE, ESCAPE + LIKE).replace(ANY, ESCAPE + ANY).toLowerCase();
ParameterExpression<String> plci = cb.parameter(String.class);
binds.put(plci, LIKE + strAttrValue + LIKE);
expr = cb.like(cb.lower(extractAttribute(entityRoot, attrName)), plci);
break;

case STARTS_WITH:
strAttrValue = attrValue.toString().replace(LIKE, ESCAPE + LIKE).replace(ANY, ESCAPE + ANY);
ParameterExpression<String> psw = cb.parameter(String.class);
binds.put(psw, strAttrValue + LIKE);
expr = cb.like(extractAttribute(entityRoot, attrName), psw);
break;

case STARTS_WITH_IGNORE_CASE:
strAttrValue = attrValue.toString().replace(LIKE, ESCAPE + LIKE).replace(ANY, ESCAPE + ANY).toLowerCase();
ParameterExpression<String> pswci = cb.parameter(String.class);
binds.put(pswci, strAttrValue + LIKE);
expr = cb.like(cb.lower(extractAttribute(entityRoot, attrName)), pswci);
break;

case IS_NULL:
expr = cb.isNull(extractAttribute(entityRoot, attrName));
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public class Devices extends AbstractKapuaResource {
* @param tagId The id of the {@link Tag} in which to search results
* @param clientId The id of the {@link Device} in which to search results
* @param connectionStatus The {@link DeviceConnectionStatus} in which to search results
* @param matchTerm A term to be matched in at least one of the configured fields of this entity
* @param fetchAttributes Additional attributes to be returned. Allowed values: connection, lastEvent
* @param askTotalCount Ask for the total count of the matched entities in the result
* @param sortParam The name of the parameter that will be used as a sorting key
Expand All @@ -77,6 +78,7 @@ public DeviceListResult simpleQuery(
@QueryParam("tagId") EntityId tagId,
@QueryParam("clientId") String clientId,
@QueryParam("status") DeviceConnectionStatus connectionStatus,
@QueryParam("matchTerm") String matchTerm,
@QueryParam("fetchAttributes") List<String> fetchAttributes,
@QueryParam("askTotalCount") boolean askTotalCount,
@QueryParam("sortParam") String sortParam,
Expand All @@ -95,10 +97,14 @@ public DeviceListResult simpleQuery(
if (connectionStatus != null) {
andPredicate.and(query.attributePredicate(DeviceAttributes.CONNECTION_STATUS, connectionStatus));
}
if (matchTerm != null && !matchTerm.isEmpty()) {
andPredicate.and(query.matchPredicate(matchTerm));
}

if (!Strings.isNullOrEmpty(sortParam)) {
query.setSortCriteria(query.fieldSortCriteria(sortParam, sortDir));
}

query.setPredicate(andPredicate);
query.setFetchAttributes(fetchAttributes);
query.setOffset(offset);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,27 @@ paths:
- $ref: '../openapi.yaml#/components/parameters/askTotalCount'
- $ref: '../openapi.yaml#/components/parameters/sortParam'
- $ref: '../openapi.yaml#/components/parameters/sortDir'
- name: matchTerm
in: query
description: |
A term to match on different fields. Every entity whose at least one of the specified fields starts with this value will be matched.
Matches on the following fields:
- CLIENT_ID
- DISPLAY_NAME
- SERIAL_NUMBER
- MODEL_ID
- MODEL_NAME
- BIOS_VERSION
- FIRMWARE_VERSION
- OS_VERSION
- JVM_VERSION
- OSGI_FRAMEWORK_VERSION
- APPLICATION_FRAMEWORK_VERSION
- CONNECTION_INTERFACE
- CONNECTION_IP
schema:
type: string
- $ref: '../openapi.yaml#/components/parameters/limit'
- $ref: '../openapi.yaml#/components/parameters/offset'
responses:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016, 2019 Eurotech and/or its affiliates and others
* Copyright (c) 2016, 2020 Eurotech and/or its affiliates and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
Expand Down Expand Up @@ -71,6 +71,17 @@ enum Operator {
* @since 1.0.0
*/
STARTS_WITH,

/**
* The same of {@link #STARTS_WITH} {@link Operator} but case insensitive
* <p>
* Matches results with value that starts with the given value, case insensitive.
* To be used with {@link String} {@link org.eclipse.kapua.model.KapuaEntityAttributes}.
*
* @since 1.2.0
*/
STARTS_WITH_IGNORE_CASE,

/**
* {@link #LIKE} {@link Operator}
* <p>
Expand All @@ -83,6 +94,18 @@ enum Operator {
*/
LIKE,

/**
* {@link #LIKE} {@link Operator} but case insensitive
* <p>
* Matches results with value that are like (in SQL fashion) the given value case insensitive.
* To be used with {@link String} {@link org.eclipse.kapua.model.KapuaEntityAttributes}.
* <p>
* If you want to match only the beginning of the {@link String} please consider using {@link #STARTS_WITH_IGNORE_CASE}.
*
* @since 1.2.0
*/
LIKE_IGNORE_CASE,

/**
* {@link #GREATER_THAN} {@link Operator}
* <p>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*******************************************************************************
* Copyright (c) 2020 Eurotech and/or its affiliates and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eurotech - initial API and implementation
*******************************************************************************/
package org.eclipse.kapua.model.query.predicate;

import java.util.List;

/**
* {@link MatchPredicate} definition.
*
* @param <T> Attribute value type.
* @since 1.2.0
*/
public interface MatchPredicate<T> extends QueryPredicate {

/**
* Gets the name of the {@link org.eclipse.kapua.model.KapuaEntityAttributes} to compare.
*
* @return The name name of the {@link org.eclipse.kapua.model.KapuaEntityAttributes} to compare.
* @since 1.0.0
*/
List<String> getAttributeNames();

/**
* Gets the value to compare the results.
*
* @return The value to compare the results.
* @since 1.0.0
*/
T getMatchTerm();

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2011, 2018 Eurotech and/or its affiliates and others
* Copyright (c) 2011, 2020 Eurotech and/or its affiliates and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
Expand All @@ -15,7 +15,7 @@

/**
* {@link DeviceQuery} predicates.
*
*
* @since 1.0.0
*/
public class DeviceAttributes extends KapuaUpdatableEntityAttributes {
Expand Down Expand Up @@ -64,6 +64,11 @@ public class DeviceAttributes extends KapuaUpdatableEntityAttributes {
*/
public static final String CONNECTION_CLIENT_ID = CONNECTION + ".clientId";

/**
* Connection Client IP
*/
public static final String CLIENT_IP = CONNECTION + ".clientIp";

/**
* Last event
*/
Expand Down Expand Up @@ -99,6 +104,10 @@ public class DeviceAttributes extends KapuaUpdatableEntityAttributes {
* Model identifier
*/
public static final String MODEL_ID = "modelId";
/**
* Model name
*/
public static final String MODEL_NAME = "modelName";
/**
* Bios version
*/
Expand Down Expand Up @@ -159,7 +168,6 @@ public class DeviceAttributes extends KapuaUpdatableEntityAttributes {
* Gps latitude
*/
public static final String GPS_LATITUDE = "gpsLatitude";

/**
* Device status
*/
Expand All @@ -172,4 +180,12 @@ public class DeviceAttributes extends KapuaUpdatableEntityAttributes {
* Preferred user identifier
*/
public static final String PREFERRED_USER_ID = "preferredUserId";
/**
* Connection Interface
*/
public static final String CONNECTION_INTERFACE = "connectionInterface";
/**
* Connection IP
*/
public static final String CONNECTION_IP = "connectionIp";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*******************************************************************************
* Copyright (c) 2020 Eurotech and/or its affiliates and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eurotech - initial API and implementation
*******************************************************************************/
package org.eclipse.kapua.service.device.registry;

import java.util.ArrayList;
import java.util.Arrays;

import org.eclipse.kapua.commons.model.query.predicate.AbstractMatchPredicate;

public class DeviceMatchPredicate<T> extends AbstractMatchPredicate<T> {

/**
* Constructor.
* <p>
*
* @param matchTerm
* @since 1.2.0
*/
public DeviceMatchPredicate(T matchTerm) {
this.attributeNames = new ArrayList<>(Arrays.asList(
DeviceAttributes.CLIENT_ID,
DeviceAttributes.DISPLAY_NAME,
DeviceAttributes.SERIAL_NUMBER,
DeviceAttributes.MODEL_ID,
DeviceAttributes.MODEL_NAME,
DeviceAttributes.BIOS_VERSION,
DeviceAttributes.FIRMWARE_VERSION,
DeviceAttributes.OS_VERSION,
DeviceAttributes.JVM_VERSION,
DeviceAttributes.OSGI_FRAMEWORK_VERSION,
DeviceAttributes.APPLICATION_FRAMEWORK_VERSION,
DeviceAttributes.CONNECTION_INTERFACE,
DeviceAttributes.CONNECTION_IP)
);
this.matchTerm = matchTerm;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2011, 2017 Eurotech and/or its affiliates and others
* Copyright (c) 2011, 2020 Eurotech and/or its affiliates and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
Expand All @@ -20,7 +20,7 @@

/**
* {@link Device} query definition.
*
*
* @since 1.0.0
*
*/
Expand All @@ -29,4 +29,6 @@
@XmlType(factoryClass = DeviceXmlRegistry.class, factoryMethod = "newQuery")
public interface DeviceQuery extends KapuaQuery<Device> {

<T> DeviceMatchPredicate<T> matchPredicate(T matchTerm);

}
Loading

0 comments on commit e89ce59

Please sign in to comment.