added a way to remove statuses of specific data types

This commit is contained in:
Dmitry Toptygin
2021-01-13 20:49:00 -05:00
parent 404aa89fb0
commit 69ca9b830b
19 changed files with 547 additions and 64 deletions

View File

@@ -134,8 +134,10 @@ public class StatusDatastoreCassandra implements StatusDatastore {
private static final String CQL_INSERT_BY_DATATYPE =
"insert into status_by_datatype (customerId, equipmentId, statusDataType) values ( ?, ?, ? )";
private static final String CQL_DELETE_BY_DATATYPE =
"delete from status_by_datatype where customerId = ? and equipmentId = ? and statusDataType = ?";
private static final String CQL_DELETE_BY_DATATYPE_HEADER =
"delete from status_by_datatype where customerId = ? and equipmentId = ? ";
private static final String CQL_DELETE_BY_DATATYPE = CQL_DELETE_BY_DATATYPE_HEADER + " and statusDataType = ?";
private static final RowMapper<Status> statusRowMapper = new StatusRowMapper();
@@ -280,6 +282,75 @@ public class StatusDatastoreCassandra implements StatusDatastore {
return ret;
}
@Override
public List<Status> delete(int customerId, long equipmentId, Set<StatusDataType> statusDataTypes) {
if(statusDataTypes == null || statusDataTypes.isEmpty()) {
return delete(customerId, equipmentId);
}
List<Status> ret = getForEquipment(customerId, Set.of(equipmentId), statusDataTypes);
//
// Delete from the main table
//
String query = CQL_DELETE;
// add filters for the query
ArrayList<Object> queryArgs = new ArrayList<>();
queryArgs.add(customerId);
queryArgs.add(equipmentId);
//add statusDataType filters
if (statusDataTypes != null && !statusDataTypes.isEmpty()) {
statusDataTypes.forEach(sdt -> queryArgs.add(sdt.getId()));
StringBuilder strb = new StringBuilder(100);
strb.append(" and statusDataType in (");
strb.append("?,".repeat(statusDataTypes.size()));
// remove last ','
strb.deleteCharAt(strb.length() - 1);
strb.append(") ");
query += strb.toString();
}
PreparedStatement preparedStmt = cqlSession.prepare(query);
cqlSession.execute(preparedStmt.bind(queryArgs.toArray()));
//
// Clear the index table
//
query = CQL_DELETE_BY_DATATYPE_HEADER;
// add filters for the query
queryArgs.clear();
queryArgs.add(customerId);
queryArgs.add(equipmentId);
//add statusDataType filters
if (statusDataTypes != null && !statusDataTypes.isEmpty()) {
statusDataTypes.forEach(sdt -> queryArgs.add(sdt.getId()));
StringBuilder strb = new StringBuilder(100);
strb.append(" and statusDataType in (");
strb.append("?,".repeat(statusDataTypes.size()));
// remove last ','
strb.deleteCharAt(strb.length() - 1);
strb.append(") ");
query += strb.toString();
}
preparedStmt = cqlSession.prepare(query);
cqlSession.execute(preparedStmt.bind(queryArgs.toArray()));
LOG.debug("Deleted Statuses {}", ret);
return ret;
}
public List<Status> get(int customerId, long equipmentId) {
LOG.debug("calling get({},{})", customerId, equipmentId);

View File

@@ -22,6 +22,7 @@ import com.telecominfraproject.wlan.core.model.pagination.ColumnAndSort;
import com.telecominfraproject.wlan.core.model.pagination.PaginationContext;
import com.telecominfraproject.wlan.core.model.pagination.PaginationResponse;
import com.telecominfraproject.wlan.core.model.pagination.SortOrder;
import com.telecominfraproject.wlan.status.dashboard.models.CustomerPortalDashboardStatus;
import com.telecominfraproject.wlan.status.equipment.models.EquipmentAdminStatusData;
import com.telecominfraproject.wlan.status.equipment.models.EquipmentProtocolStatusData;
import com.telecominfraproject.wlan.status.equipment.report.models.OperatingSystemPerformance;
@@ -29,6 +30,7 @@ import com.telecominfraproject.wlan.status.models.Status;
import com.telecominfraproject.wlan.status.models.StatusCode;
import com.telecominfraproject.wlan.status.models.StatusDataType;
import com.telecominfraproject.wlan.status.models.StatusDetails;
import com.telecominfraproject.wlan.status.network.models.NetworkAggregateStatusData;
/**
* @author dtoptygin
@@ -803,6 +805,55 @@ public abstract class BaseStatusDatastoreTest {
allCreatedStatuses.forEach(s -> testInterface.delete(s.getCustomerId(), s.getEquipmentId()));
}
@Test
public void testDelete() {
//create
Status status1 = testInterface.update(createStatusObject());
Status status2 = new Status();
status2.setCustomerId(status1.getCustomerId());
status2.setEquipmentId(status1.getEquipmentId());
status2.setDetails(new EquipmentProtocolStatusData());
status2 = testInterface.update(status2);
Status status3 = new Status();
status3.setCustomerId(status1.getCustomerId());
status3.setEquipmentId(status1.getEquipmentId());
status3.setDetails(new NetworkAggregateStatusData());
status3 = testInterface.update(status3);
List<Status> statusList = testInterface.getForEquipment(status1.getCustomerId(), Set.of(status1.getEquipmentId()), null);
assertEquals(3, statusList.size());
//delete with specific data types
List<Status> deletedList = testInterface.delete(status1.getCustomerId(), status1.getEquipmentId(), Set.of(StatusDataType.PROTOCOL, StatusDataType.NETWORK_AGGREGATE));
assertEquals(2, deletedList.size());
statusList = testInterface.getForEquipment(status1.getCustomerId(), Set.of(status1.getEquipmentId()), null);
assertEquals(1, statusList.size());
//now test delete with null data types
deletedList = testInterface.delete(status1.getCustomerId(), status1.getEquipmentId(), null);
assertEquals(1, deletedList.size());
statusList = testInterface.getForEquipment(status1.getCustomerId(), Set.of(status1.getEquipmentId()), null);
assertEquals(0, statusList.size());
//now test delete with empty data types
Status status4 = new Status();
status4.setCustomerId(status1.getCustomerId());
status4.setEquipmentId(status1.getEquipmentId());
status4.setDetails(new CustomerPortalDashboardStatus());
status4 = testInterface.update(status4);
deletedList = testInterface.delete(status1.getCustomerId(), status1.getEquipmentId(), Set.of());
assertEquals(1, deletedList.size());
statusList = testInterface.getForEquipment(status1.getCustomerId(), Set.of(status1.getEquipmentId()), null);
assertEquals(0, statusList.size());
}
protected Status createStatusObject() {
Status result = new Status();

View File

@@ -107,12 +107,11 @@ public class StatusDatastoreInMemory extends BaseInMemoryDatastore implements St
}
@Override
public List<Status> delete(int customerId, long equipmentId) {
public List<Status> delete(int customerId, long equipmentId, Set<StatusDataType> dataTypes) {
List<CustomerEquipmentStatusId> keysToRemove = new ArrayList<>();
idToStatusMap.keySet().forEach(k -> {
if (k.customerId == customerId && k.equipmentId == equipmentId) {
if (k.customerId == customerId && k.equipmentId == equipmentId && (dataTypes == null || dataTypes.isEmpty() || dataTypes.contains(k.statusDataType) ) ) {
keysToRemove.add(k);
}
});

View File

@@ -28,13 +28,25 @@ public interface StatusDatastore {
Status update(Status status);
/**
* Deletes a list of Status records for a given customer equipment.
* Deletes all Status records for a given customer equipment.
*
* @param customerId
* @param equipmentId
* @return list of deleted Status objects.
*/
List<Status> delete(int customerId, long equipmentId);
default public List<Status> delete(int customerId, long equipmentId){
return delete(customerId, equipmentId, null);
}
/**
* Deletes Status records for a given customer equipment.
*
* @param customerId
* @param equipmentId
* @param statusDataTypes - null or empty means delete all
* @return list of deleted Status objects.
*/
List<Status> delete(int customerId, long equipmentId, Set<StatusDataType> statusDataTypes);
/**
* Force bulk update of the status objects. If a particular record was not there, it will be created. LastModifiedTs checks are not enforced in this method, it will overwrite any previously stored status object.

View File

@@ -301,10 +301,31 @@ public class StatusDAO extends BaseJdbcDao {
return ret;
}
public List<Status> delete(int customerId, long equipmentId) {
List<Status> ret = get(customerId, equipmentId);
public List<Status> delete(int customerId, long equipmentId, Set<StatusDataType> statusDataTypes) {
List<Status> ret = getForEquipment(customerId, Set.of(equipmentId), statusDataTypes);
this.jdbcTemplate.update(SQL_DELETE, customerId, equipmentId);
String query = SQL_DELETE;
// add filters for the query
ArrayList<Object> queryArgs = new ArrayList<>();
queryArgs.add(customerId);
queryArgs.add(equipmentId);
//add statusDataType filters
if (statusDataTypes != null && !statusDataTypes.isEmpty()) {
statusDataTypes.forEach(sdt -> queryArgs.add(sdt.getId()));
StringBuilder strb = new StringBuilder(100);
strb.append("and statusDataType in (");
strb.append("?,".repeat(statusDataTypes.size()));
// remove last ','
strb.deleteCharAt(strb.length() - 1);
strb.append(") ");
query += strb.toString();
}
this.jdbcTemplate.update(query, queryArgs.toArray());
LOG.debug("Deleted Statuses {}", ret);
@@ -361,12 +382,9 @@ public class StatusDAO extends BaseJdbcDao {
StringBuilder strb = new StringBuilder(100);
strb.append("and equipmentId in (");
for (int i = 0; i < equipmentIds.size(); i++) {
strb.append("?");
if (i < equipmentIds.size() - 1) {
strb.append(",");
}
}
strb.append("?,".repeat(equipmentIds.size()));
// remove last ','
strb.deleteCharAt(strb.length() - 1);
strb.append(") ");
query += strb.toString();
@@ -378,12 +396,9 @@ public class StatusDAO extends BaseJdbcDao {
StringBuilder strb = new StringBuilder(100);
strb.append("and statusDataType in (");
for (int i = 0; i < statusDataTypes.size(); i++) {
strb.append("?");
if (i < statusDataTypes.size() - 1) {
strb.append(",");
}
}
strb.append("?,".repeat(statusDataTypes.size()));
// remove last ','
strb.deleteCharAt(strb.length() - 1);
strb.append(") ");
query += strb.toString();
@@ -472,12 +487,9 @@ public class StatusDAO extends BaseJdbcDao {
StringBuilder strb = new StringBuilder(100);
strb.append("and equipmentId in (");
for (int i = 0; i < equipmentIds.size(); i++) {
strb.append("?");
if (i < equipmentIds.size() - 1) {
strb.append(",");
}
}
strb.append("?,".repeat(equipmentIds.size()));
// remove last ','
strb.deleteCharAt(strb.length() - 1);
strb.append(") ");
query += strb.toString();
@@ -489,12 +501,9 @@ public class StatusDAO extends BaseJdbcDao {
StringBuilder strb = new StringBuilder(100);
strb.append("and statusDataType in (");
for (int i = 0; i < statusDataTypes.size(); i++) {
strb.append("?");
if (i < statusDataTypes.size() - 1) {
strb.append(",");
}
}
strb.append("?,".repeat(statusDataTypes.size()));
// remove last ','
strb.deleteCharAt(strb.length() - 1);
strb.append(") ");
query += strb.toString();

View File

@@ -34,8 +34,8 @@ public class StatusDatastoreRdbms implements StatusDatastore {
}
@Override
public List<Status> delete(int customerId, long equipmentId) {
return statusDAO.delete(customerId, equipmentId);
public List<Status> delete(int customerId, long equipmentId, Set<StatusDataType> statusDataTypes) {
return statusDAO.delete(customerId, equipmentId, statusDataTypes);
}
@Override

View File

@@ -60,7 +60,7 @@ public class StatusDatastoreRdbmsPlumbingTests extends BaseJdbcTest {
Status ret = statusDatastore.getOrNull(1,1L, StatusDataType.getById(1));
//DELETE Test
statusDAO.delete(ret.getCustomerId(), ret.getEquipmentId());
statusDAO.delete(ret.getCustomerId(), ret.getEquipmentId(), null);
assertNull(statusDatastore.getOrNull(1,1L, StatusDataType.getById(1)));

View File

@@ -1,6 +1,8 @@
package com.telecominfraproject.wlan.status.models;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -50,7 +52,7 @@ public class StatusDataType implements EnumWithId {
/**
* Equipment Administrative status
*/
EQUIPMENT_ADMIN = new StatusDataType(1, "EQUIPMENT_ADMIN") ,
EQUIPMENT_ADMIN = new StatusDataType(1, "EQUIPMENT_ADMIN", Set.of(StatusTrait.DeleteOnEquipmentDisconnect)) ,
/**
* Network Administrative status
*/
@@ -62,7 +64,7 @@ public class StatusDataType implements EnumWithId {
/**
* Protocol status
*/
PROTOCOL = new StatusDataType(4, "PROTOCOL") ,
PROTOCOL = new StatusDataType(4, "PROTOCOL", Set.of(StatusTrait.DeleteOnEquipmentDisconnect)) ,
/**
* Firmware upgrade status
*/
@@ -70,22 +72,22 @@ public class StatusDataType implements EnumWithId {
/**
* Peer status
*/
PEERINFO = new StatusDataType(6, "PEERINFO"),
PEERINFO = new StatusDataType(6, "PEERINFO", Set.of(StatusTrait.DeleteOnEquipmentDisconnect)),
/**
* LAN status
*/
LANINFO = new StatusDataType(7, "LANINFO"),
LANINFO = new StatusDataType(7, "LANINFO", Set.of(StatusTrait.DeleteOnEquipmentDisconnect)),
/**
* Neighbouring information status
*/
NEIGHBOURINGINFO = new StatusDataType(8, "NEIGHBOURINGINFO"),
// These are from EquipmentReportType
OS_PERFORMANCE = new StatusDataType(9, "OS_PERFORMANCE"),
OS_PERFORMANCE = new StatusDataType(9, "OS_PERFORMANCE", Set.of(StatusTrait.DeleteOnEquipmentDisconnect)),
NEIGHBOUR_SCAN = new StatusDataType(10, "NEIGHBOUR_SCAN"),
RADIO_UTILIZATION = new StatusDataType(11, "RADIO_UTILIZATION"),
ACTIVE_BSSIDS = new StatusDataType(12, "ACTIVE_BSSIDS"),
CLIENT_DETAILS = new StatusDataType(13, "CLIENT_DETAILS"),
RADIO_UTILIZATION = new StatusDataType(11, "RADIO_UTILIZATION", Set.of(StatusTrait.DeleteOnEquipmentDisconnect)),
ACTIVE_BSSIDS = new StatusDataType(12, "ACTIVE_BSSIDS", Set.of(StatusTrait.DeleteOnEquipmentDisconnect)),
CLIENT_DETAILS = new StatusDataType(13, "CLIENT_DETAILS", Set.of(StatusTrait.DeleteOnEquipmentDisconnect)),
CUSTOMER_DASHBOARD = new StatusDataType(14, "CUSTOMER_DASHBOARD"),
@@ -107,14 +109,23 @@ public class StatusDataType implements EnumWithId {
private final int id;
private final String name;
private final Set<StatusTrait> traits = new HashSet<>();
protected StatusDataType(int id, String name) {
this(id, name, null);
}
protected StatusDataType(int id, String name, Set<StatusTrait> traits) {
synchronized(lock) {
LOG.debug("Registering StatusDataType by {} : {}", this.getClass().getSimpleName(), name);
this.id = id;
this.name = name;
if(traits!=null) {
this.traits.addAll(traits);
}
ELEMENTS_BY_NAME.values().forEach(s -> {
if(s.getName().equals(name)) {
@@ -196,4 +207,18 @@ public class StatusDataType implements EnumWithId {
return name;
}
public boolean supportsTrait(StatusTrait incomingTrait) {
return incomingTrait==null || this.traits.contains(incomingTrait);
}
public boolean supportsTraits(Collection<StatusTrait> incomingTraits) {
return incomingTraits==null || this.traits.containsAll(incomingTraits);
}
public static Set<StatusDataType> getByTraits(Collection<StatusTrait> incomingTraits){
Set<StatusDataType> ret = new HashSet<>();
ELEMENTS.values().forEach(v -> { if(v.supportsTraits(incomingTraits)) {ret.add(v);} });
return ret;
}
}

View File

@@ -0,0 +1,160 @@
package com.telecominfraproject.wlan.status.models;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.telecominfraproject.wlan.core.model.extensibleenum.EnumWithId;
import com.telecominfraproject.wlan.core.model.json.BaseJsonModel;
/**
* All available status traits that can be handled by the CloudSDK.
* Status traits are specific features/bahaviours associated with certain status data types.
* They are used together with StatusDataType enum to determine which data types are affected by a certain feature.
*
* <br>This enumeration-like class can be extended by vendors - new elements can be defined by extending this class like so:
* <br>
* <pre>
* public class VendorExtendedStatusTrait extends StatusTrait {
*
* public static final StatusTrait
* VENDOR_STATUS_TRAIT_A = new VendorExtendedStatusTrait(100, "VENDOR_STATUS_TRAIT_A") ,
* VENDOR_STATUS_TRAIT_B = new VendorExtendedStatusTrait(101, "VENDOR_STATUS_TRAIT_B")
* ;
*
* private VendorExtendedStatusTrait(int id, String name) {
* super(id, name);
* }
*
* }
* </pre>
* @see com.telecominfraproject.wlan.core.model.extensibleenum.EnumWithId
* @see com.telecominfraproject.wlan.status.models.vendorextensions.TestVendorExtendedStatusModel
* <br>
* @author dtop
*
*/
public class StatusTrait implements EnumWithId {
private static final Logger LOG = LoggerFactory.getLogger(StatusTrait.class);
private static Object lock = new Object();
private static final Map<Integer, StatusTrait> ELEMENTS = new ConcurrentHashMap<>();
private static final Map<String, StatusTrait> ELEMENTS_BY_NAME = new ConcurrentHashMap<>();
public static final StatusTrait
DeleteOnEquipmentDisconnect = new StatusTrait(1, "DeleteOnEquipmentDisconnect") ,
UNSUPPORTED = new StatusTrait(-1, "UNSUPPORTED") ;
static {
//try to load all the subclasses explicitly - to avoid timing issues when items coming from subclasses may be registered some time later, after the parent class is loaded
Set<Class<? extends StatusTrait>> subclasses = BaseJsonModel.getReflections().getSubTypesOf(StatusTrait.class);
for(Class<?> cls: subclasses) {
try {
Class.forName(cls.getName());
} catch (ClassNotFoundException e) {
LOG.warn("Cannot load class {} : {}", cls.getName(), e);
}
}
}
private final int id;
private final String name;
protected StatusTrait(int id, String name) {
synchronized(lock) {
LOG.debug("Registering StatusTrait by {} : {}", this.getClass().getSimpleName(), name);
this.id = id;
this.name = name;
ELEMENTS_BY_NAME.values().forEach(s -> {
if(s.getName().equals(name)) {
throw new IllegalStateException("StatusTrait item for "+ name + " is already defined, cannot have more than one of them");
}
});
if(ELEMENTS.containsKey(id)) {
throw new IllegalStateException("StatusTrait item "+ name + "("+id+") is already defined, cannot have more than one of them");
}
ELEMENTS.put(id, this);
ELEMENTS_BY_NAME.put(name, this);
}
}
@Override
public int getId() {
return id;
}
@Override
public String getName() {
return name;
}
@JsonIgnore
public String name() {
return name;
}
@JsonIgnore
public static StatusTrait[] values() {
return new ArrayList<>(ELEMENTS.values()).toArray(new StatusTrait[0]);
}
public static StatusTrait getById(int enumId){
return ELEMENTS.get(enumId);
}
@JsonCreator
public static StatusTrait getByName(String value) {
StatusTrait ret = ELEMENTS_BY_NAME.get(value);
if (ret == null) {
ret = UNSUPPORTED;
}
return ret;
}
public static List<StatusTrait> getValues() {
return new ArrayList<>(ELEMENTS.values());
}
public static boolean isUnsupported(StatusTrait value) {
return (UNSUPPORTED.equals(value));
}
@Override
public int hashCode() {
return id;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof StatusTrait)) {
return false;
}
StatusTrait other = (StatusTrait) obj;
return id == other.id;
}
@Override
public String toString() {
return name;
}
}

View File

@@ -1,11 +1,18 @@
package com.telecominfraproject.wlan.status.models.vendorextensions;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import com.telecominfraproject.wlan.core.model.json.BaseJsonModel;
import com.telecominfraproject.wlan.status.models.StatusDataType;
import com.telecominfraproject.wlan.status.models.StatusTrait;
public class TestVendorExtentions {
@@ -25,4 +32,32 @@ public class TestVendorExtentions {
}
@Test
public void testExtendedTraits() {
assertTrue(StatusDataType.EQUIPMENT_ADMIN.supportsTrait(StatusTrait.DeleteOnEquipmentDisconnect));
assertTrue(StatusDataType.EQUIPMENT_ADMIN.supportsTrait(null));
assertTrue(StatusDataType.EQUIPMENT_ADMIN.supportsTraits(null));
assertTrue(StatusDataType.EQUIPMENT_ADMIN.supportsTraits(Set.of(StatusTrait.DeleteOnEquipmentDisconnect)));
assertFalse(VendorExtendedStatusDataType.VENDOR_STATUS_A.supportsTraits(Set.of(StatusTrait.DeleteOnEquipmentDisconnect)));
assertTrue(VendorExtendedStatusDataType.VENDOR_STATUS_A.supportsTraits(Set.of(VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_A)));
assertTrue(VendorExtendedStatusDataType.VENDOR_STATUS_A.supportsTraits(Set.of(VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_B)));
assertTrue(VendorExtendedStatusDataType.VENDOR_STATUS_A.supportsTraits(Set.of(VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_A, VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_B)));
assertFalse(VendorExtendedStatusDataType.VENDOR_STATUS_B.supportsTraits(Set.of(VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_A)));
assertFalse(VendorExtendedStatusDataType.VENDOR_STATUS_B.supportsTraits(Set.of(VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_B)));
assertFalse(VendorExtendedStatusDataType.VENDOR_STATUS_B.supportsTraits(Set.of(VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_A, VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_B)));
assertFalse(VendorExtendedStatusDataType.VENDOR_STATUS_C.supportsTraits(Set.of(VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_A)));
assertTrue(VendorExtendedStatusDataType.VENDOR_STATUS_C.supportsTraits(Set.of(VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_B)));
assertFalse(VendorExtendedStatusDataType.VENDOR_STATUS_C.supportsTraits(Set.of(VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_A, VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_B)));
assertEquals(Set.of(VendorExtendedStatusDataType.VENDOR_STATUS_A), VendorExtendedStatusDataType.getByTraits(Set.of(VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_A)));
assertEquals(Set.of(VendorExtendedStatusDataType.VENDOR_STATUS_A, VendorExtendedStatusDataType.VENDOR_STATUS_C), VendorExtendedStatusDataType.getByTraits(Set.of(VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_B)));
assertEquals(Set.of(VendorExtendedStatusDataType.VENDOR_STATUS_A), VendorExtendedStatusDataType.getByTraits(Set.of(VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_A, VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_B)));
assertEquals(new HashSet<>(StatusDataType.getValues()), VendorExtendedStatusDataType.getByTraits(null));
assertEquals(new HashSet<>(StatusDataType.getValues()), VendorExtendedStatusDataType.getByTraits(Collections.emptyList()));
}
}

View File

@@ -1,16 +1,24 @@
package com.telecominfraproject.wlan.status.models.vendorextensions;
import java.util.Set;
import com.telecominfraproject.wlan.status.models.StatusDataType;
import com.telecominfraproject.wlan.status.models.StatusTrait;
public class VendorExtendedStatusDataType extends StatusDataType {
public static final StatusDataType
VENDOR_STATUS_A = new VendorExtendedStatusDataType(100, "VENDOR_STATUS_A") ,
VENDOR_STATUS_B = new VendorExtendedStatusDataType(101, "VENDOR_STATUS_B")
VENDOR_STATUS_A = new VendorExtendedStatusDataType(100, "VENDOR_STATUS_A", Set.of(VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_A, VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_B)) ,
VENDOR_STATUS_B = new VendorExtendedStatusDataType(101, "VENDOR_STATUS_B"),
VENDOR_STATUS_C = new VendorExtendedStatusDataType(102, "VENDOR_STATUS_C", Set.of(VendorExtendedStatusTrait.VENDOR_STATUS_TRAIT_B))
;
private VendorExtendedStatusDataType(int id, String name) {
super(id, name);
this(id, name, null);
}
private VendorExtendedStatusDataType(int id, String name, Set<StatusTrait> traits) {
super(id, name, traits);
}
}

View File

@@ -0,0 +1,16 @@
package com.telecominfraproject.wlan.status.models.vendorextensions;
import com.telecominfraproject.wlan.status.models.StatusTrait;
public class VendorExtendedStatusTrait extends StatusTrait {
public static final StatusTrait
VENDOR_STATUS_TRAIT_A = new VendorExtendedStatusTrait(100, "VENDOR_STATUS_TRAIT_A") ,
VENDOR_STATUS_TRAIT_B = new VendorExtendedStatusTrait(101, "VENDOR_STATUS_TRAIT_B")
;
private VendorExtendedStatusTrait(int id, String name) {
super(id, name);
}
}

View File

@@ -9,6 +9,7 @@ import com.telecominfraproject.wlan.core.model.pagination.PaginationResponse;
import com.telecominfraproject.wlan.status.models.Status;
import com.telecominfraproject.wlan.status.models.StatusDataType;
import com.telecominfraproject.wlan.status.models.StatusTrait;
/**
@@ -27,13 +28,38 @@ public interface StatusServiceInterface {
Status update(Status status);
/**
* Deletes a list of Status records for a given customer equipment.
* Deletes all Status records for a given customer equipment.
*
* @param customerId
* @param equipmentId
* @return list of deleted Status objects.
*/
List<Status> delete(int customerId, long equipmentId);
default public List<Status> delete(int customerId, long equipmentId){
return delete(customerId, equipmentId, null);
}
/**
* Deletes Status records for a given customer equipment.
* Only Statuses that are marked with trait DeleteOnEquipmentDisconnect are deleted.
*
* @param customerId
* @param equipmentId
* @return list of deleted Status objects.
*/
default public List<Status> deleteOnEquipmentDisconnect(int customerId, long equipmentId){
return delete(customerId, equipmentId, StatusDataType.getByTraits(Set.of(StatusTrait.DeleteOnEquipmentDisconnect)));
}
/**
* Deletes Status records for a given customer equipment.
*
* @param customerId
* @param equipmentId
* @param statusDataTypes - null or empty means delete all
* @return list of deleted Status objects.
*/
List<Status> delete(int customerId, long equipmentId, Set<StatusDataType> statusDataTypes);
/**
* Force bulk update of the status objects. If a particular record was not there, it will be created. LastModifiedTs checks are not enforced in this method, it will overwrite any previously stored status object.

View File

@@ -72,8 +72,8 @@ public class StatusServiceLocal implements StatusServiceInterface {
@Override
public List<Status> delete(int customerId, long equipmentId) {
return statusController.delete(customerId, equipmentId);
public List<Status> delete(int customerId, long equipmentId, Set<StatusDataType> statusDataTypes) {
return statusController.delete(customerId, equipmentId, statusDataTypes);
}
}

View File

@@ -223,24 +223,34 @@ public class StatusServiceRemote extends BaseRemoteClient implements StatusServi
}
@Override
public List<Status> delete(int customerId, long equipmentId) {
public List<Status> delete(int customerId, long equipmentId, Set<StatusDataType> statusDataTypes) {
LOG.debug("delete({}, {})", customerId, equipmentId);
LOG.debug("delete({}, {}, {})", customerId, equipmentId, statusDataTypes);
String statusDataTypesStr = null;
if (statusDataTypes != null && !statusDataTypes.isEmpty()) {
statusDataTypesStr = statusDataTypes.toString();
// remove [] around the string, otherwise will get:
// Failed to convert value of type 'java.lang.String' to required
// type 'java.util.Set'; nested exception is
// java.lang.NumberFormatException: For input string: "[690]"
statusDataTypesStr = statusDataTypesStr.substring(1, statusDataTypesStr.length() - 1);
}
try {
ResponseEntity<List<Status>> responseEntity = restTemplate.exchange(
getBaseUrl() + "?customerId={customerId}&equipmentId={equipmentId}", HttpMethod.DELETE,
null, Status_LIST_CLASS_TOKEN, customerId, equipmentId);
getBaseUrl() + "?customerId={customerId}&equipmentId={equipmentId}&statusDataTypes={statusDataTypesStr}", HttpMethod.DELETE,
null, Status_LIST_CLASS_TOKEN, customerId, equipmentId, statusDataTypesStr);
List<Status> result = responseEntity.getBody();
if (null == result) {
result = Collections.emptyList();
}
LOG.debug("delete({}, {}) returns {} entries", customerId, equipmentId, result.size());
LOG.debug("delete({}, {}, {}) returns {} entries", customerId, equipmentId, statusDataTypes, result.size());
return result;
} catch (Exception exp) {
LOG.error("delete({}, {}) exception ", customerId, equipmentId, exp);
LOG.error("delete({}, {}, {}) exception ", customerId, equipmentId, statusDataTypes, exp);
throw exp;
}

View File

@@ -27,6 +27,7 @@ import com.telecominfraproject.wlan.core.model.pagination.PaginationContext;
import com.telecominfraproject.wlan.core.model.pagination.PaginationResponse;
import com.telecominfraproject.wlan.core.model.pagination.SortOrder;
import com.telecominfraproject.wlan.remote.tests.BaseRemoteTest;
import com.telecominfraproject.wlan.status.dashboard.models.CustomerPortalDashboardStatus;
import com.telecominfraproject.wlan.status.equipment.models.EquipmentAdminStatusData;
import com.telecominfraproject.wlan.status.equipment.models.EquipmentProtocolStatusData;
import com.telecominfraproject.wlan.status.equipment.report.models.OperatingSystemPerformance;
@@ -35,6 +36,7 @@ import com.telecominfraproject.wlan.status.models.StatusCode;
import com.telecominfraproject.wlan.status.models.StatusDataType;
import com.telecominfraproject.wlan.status.models.StatusDetails;
import com.telecominfraproject.wlan.status.network.models.NetworkAdminStatusData;
import com.telecominfraproject.wlan.status.network.models.NetworkAggregateStatusData;
/**
* @author dtoptygin
@@ -96,6 +98,53 @@ public class StatusServiceRemoteTest extends BaseRemoteTest {
}
@Test
public void testDelete() {
//create
Status status1 = remoteInterface.update(createStatusObject());
Status status2 = new Status();
status2.setCustomerId(status1.getCustomerId());
status2.setEquipmentId(status1.getEquipmentId());
status2.setDetails(new EquipmentProtocolStatusData());
status2 = remoteInterface.update(status2);
Status status3 = new Status();
status3.setCustomerId(status1.getCustomerId());
status3.setEquipmentId(status1.getEquipmentId());
status3.setDetails(new NetworkAggregateStatusData());
status3 = remoteInterface.update(status3);
List<Status> statusList = remoteInterface.getForEquipment(status1.getCustomerId(), Set.of(status1.getEquipmentId()), null);
assertEquals(3, statusList.size());
//delete
List<Status> deletedList = remoteInterface.delete(status1.getCustomerId(), status1.getEquipmentId(), Set.of(StatusDataType.PROTOCOL, StatusDataType.NETWORK_AGGREGATE));
assertEquals(2, deletedList.size());
statusList = remoteInterface.getForEquipment(status1.getCustomerId(), Set.of(status1.getEquipmentId()), null);
assertEquals(1, statusList.size());
deletedList = remoteInterface.delete(status1.getCustomerId(), status1.getEquipmentId(), null);
assertEquals(1, deletedList.size());
statusList = remoteInterface.getForEquipment(status1.getCustomerId(), Set.of(status1.getEquipmentId()), null);
assertEquals(0, statusList.size());
//now test delete with empty data types
Status status4 = new Status();
status4.setCustomerId(status1.getCustomerId());
status4.setEquipmentId(status1.getEquipmentId());
status4.setDetails(new CustomerPortalDashboardStatus());
status4 = remoteInterface.update(status4);
deletedList = remoteInterface.delete(status1.getCustomerId(), status1.getEquipmentId(), Set.of());
assertEquals(1, deletedList.size());
statusList = remoteInterface.getForEquipment(status1.getCustomerId(), Set.of(status1.getEquipmentId()), null);
assertEquals(0, statusList.size());
}
@Test
public void testNetworkAdminStatusDataCRUD() {
Status status = new Status();

View File

@@ -213,17 +213,19 @@ public class StatusController {
/**
* Deletes Status record
* @param statusDataTypes
*
* @param statusId
* @return deleted Status object
*/
@RequestMapping(method=RequestMethod.DELETE)
public ListOfStatuses delete(@RequestParam int customerId, @RequestParam long equipmentId) {
LOG.debug("delete({},{})", customerId, equipmentId);
public ListOfStatuses delete(@RequestParam int customerId, @RequestParam long equipmentId,
@RequestParam(required = false) Set<StatusDataType> statusDataTypes) {
LOG.debug("delete({},{}, {})", customerId, equipmentId, statusDataTypes);
List<Status> ret = statusDatastore.delete(customerId, equipmentId);
List<Status> ret = statusDatastore.delete(customerId, equipmentId, statusDataTypes);
LOG.debug("deleted statuses ({},{})", customerId, equipmentId);
LOG.debug("deleted statuses ({},{},{})", customerId, equipmentId,statusDataTypes);
List<SystemEvent> events = new ArrayList<>();
ret.forEach(s -> events.add(new StatusRemovedEvent(s)));

View File

@@ -1401,6 +1401,16 @@ paths:
schema:
type: integer
format: int64
- name: statusDataTypes
in: query
description: Status Data Types
required: false
content:
text/plain:
schema:
type: array
items:
$ref: '#/components/schemas/StatusDataType'
responses:
200:
description: Successful operation

View File

@@ -70,7 +70,7 @@ public class StatusControllerTest {
assertEqualStatuss(status, ret);
//Delete - success
statusController.delete(ret.getCustomerId(), ret.getEquipmentId());
statusController.delete(ret.getCustomerId(), ret.getEquipmentId(), null);
}