mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-15 10:18:45 +00:00
bug6059: removed Igtimi "Resource" concept; all we need is their *data*;
made Selenium API tests work
This commit is contained in:
-1
@@ -102,7 +102,6 @@ public class SecuredDomainType extends HasPermissionsImpl {
|
||||
@Deprecated
|
||||
public static final HasPermissions IGTIMI_ACCOUNT = new SecuredDomainType("IGTIMI_ACCOUNT");
|
||||
public static final HasPermissions IGTIMI_DEVICE = new SecuredDomainType("IGTIMI_DEVICE");
|
||||
public static final HasPermissions IGTIMI_RESOURCE = new SecuredDomainType("IGTIMI_RESOURCE");
|
||||
public static final HasPermissions IGTIMI_DATA_ACCESS_WINDOW = new SecuredDomainType("IGTIMI_DATA_ACCESS_WINDOW");
|
||||
public static final HasPermissions SWISS_TIMING_ACCOUNT = new SecuredDomainType("SWISS_TIMING_ACCOUNT");
|
||||
public static final HasPermissions SWISS_TIMING_ARCHIVE_ACCOUNT = new SecuredDomainType(
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ public class RiotDevicesResource extends AbstractRiotServerResource {
|
||||
final Device device = new DeviceDeserializer().createDeviceFromJson(deviceJson);
|
||||
securityService.setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
|
||||
device.getPermissionType(), device.getIdentifier().getTypeRelativeObjectIdentifier(),
|
||||
device.getName(), ()->riot.addDevice(device));
|
||||
device.getName(), ()->riot.createDevice(device.getSerialNumber()));
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
|
||||
-65
@@ -1,8 +1,6 @@
|
||||
package com.sap.sailing.domain.igtimiadapter.gateway.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Base64;
|
||||
import java.util.Base64.Encoder;
|
||||
import java.util.HashMap;
|
||||
@@ -10,13 +8,8 @@ import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
@@ -29,26 +22,19 @@ import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import com.igtimi.IgtimiData.DataPoint.DataCase;
|
||||
import com.igtimi.IgtimiStream.Msg;
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sailing.domain.igtimiadapter.DataAccessWindow;
|
||||
import com.sap.sailing.domain.igtimiadapter.Device;
|
||||
import com.sap.sailing.domain.igtimiadapter.IgtimiConnection;
|
||||
import com.sap.sailing.domain.igtimiadapter.Resource;
|
||||
import com.sap.sailing.domain.igtimiadapter.datatypes.Type;
|
||||
import com.sap.sailing.domain.igtimiadapter.impl.ResourceDeserializer;
|
||||
import com.sap.sailing.domain.igtimiadapter.impl.ResourceSerializer;
|
||||
import com.sap.sailing.domain.igtimiadapter.server.riot.RiotServer;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.TimeRange;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
|
||||
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
|
||||
|
||||
@Path(RestApiApplication.API + RestApiApplication.V1 + RiotResourcesResource.RESOURCES)
|
||||
public class RiotResourcesResource extends AbstractRiotServerResource {
|
||||
@@ -56,29 +42,6 @@ public class RiotResourcesResource extends AbstractRiotServerResource {
|
||||
private static final String DATA = "/data";
|
||||
private static final String LATEST = "/latest";
|
||||
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
public Response getResources(@QueryParam("permission") String permission,
|
||||
@QueryParam("start_time") String startTime, @QueryParam("end_time") String endTime,
|
||||
@QueryParam("serial_numbers[]") Set<String> serialNumbers,
|
||||
@QueryParam("stream_ids[]") Set<String> streamIds)
|
||||
throws ClientProtocolException, IllegalStateException, IOException, ParseException {
|
||||
final RiotServer riot = Activator.getInstance().getRiotServer();
|
||||
final JSONObject result = new JSONObject();
|
||||
final JSONArray resourcesJson = new JSONArray();
|
||||
result.put("resources", resourcesJson);
|
||||
for (final Resource resource : riot.getResources()) {
|
||||
if (SecurityUtils.getSubject().isPermitted(resource.getIdentifier().getStringPermission(DefaultActions.READ))
|
||||
&& (serialNumbers.isEmpty() || serialNumbers.contains(resource.getDeviceSerialNumber()))
|
||||
&& TimeRange.create(startTime == null ? null : TimePoint.of(Long.valueOf(startTime)),
|
||||
endTime == null ? null : TimePoint.of(Long.valueOf(endTime))).intersects(
|
||||
resource.getTimeRange())) {
|
||||
resourcesJson.add(new ResourceSerializer().createJsonFromResource(resource));
|
||||
}
|
||||
}
|
||||
return Response.ok(streamingOutput(result)).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Output is the same format as for {@link #getResourcesData(UriInfo)}
|
||||
*/
|
||||
@@ -109,20 +72,6 @@ public class RiotResourcesResource extends AbstractRiotServerResource {
|
||||
return Response.ok(streamingOutput(result)).build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes("application/json;charset=UTF-8")
|
||||
public Response postResource(@Context HttpServletRequest request) throws IOException, ParseException {
|
||||
final RiotServer riot = getRiotService();
|
||||
final SecurityService securityService = getSecurityService();
|
||||
final InputStream inputStream = request.getInputStream();
|
||||
final JSONObject resourceJson = (JSONObject) new JSONParser().parse(new InputStreamReader(inputStream));
|
||||
final Resource resource = new ResourceDeserializer().createResourceFromJson(resourceJson);
|
||||
securityService.setOwnershipCheckPermissionForObjectCreationAndRevertOnError(SecuredDomainType.IGTIMI_RESOURCE,
|
||||
new TypeRelativeObjectIdentifier(Long.toString(resource.getId())), resource.getName(),
|
||||
()->riot.addResource(resource));
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* A response of a successful request contains a {@link JSONObject} where the keys are the device serial numbers,
|
||||
* and where the values are arrays of {@link String}s representing Base64-encoded binary protobuf messages that are
|
||||
@@ -185,18 +134,4 @@ public class RiotResourcesResource extends AbstractRiotServerResource {
|
||||
return subject.isPermitted(daw.getIdentifier().getStringPermission(DefaultActions.READ));
|
||||
});
|
||||
}
|
||||
|
||||
@Path("{id}")
|
||||
@DELETE
|
||||
public Response deleteResource(@PathParam("id") long id) throws IOException, ParseException {
|
||||
final RiotServer riot = getRiotService();
|
||||
final SecurityService securityService = getSecurityService();
|
||||
final Resource resource = riot.getResourceById(id);
|
||||
if (resource != null) {
|
||||
securityService.checkCurrentUserDeletePermission(resource);
|
||||
riot.removeResource(id);
|
||||
securityService.deleteAllDataForRemovedObject(resource.getIdentifier());
|
||||
}
|
||||
return Response.ok().build();
|
||||
}
|
||||
}
|
||||
|
||||
-3
@@ -9,12 +9,9 @@ import com.igtimi.IgtimiStream.Msg;
|
||||
import com.mongodb.client.ClientSession;
|
||||
import com.sap.sailing.domain.igtimiadapter.DataAccessWindow;
|
||||
import com.sap.sailing.domain.igtimiadapter.Device;
|
||||
import com.sap.sailing.domain.igtimiadapter.Resource;
|
||||
import com.sap.sse.common.TimeRange;
|
||||
|
||||
public interface DomainObjectFactory {
|
||||
Iterable<Resource> getResources(ClientSession clientSessionOrNull);
|
||||
|
||||
Iterable<DataAccessWindow> getDataAccessWindows(ClientSession clientSessionOrNull);
|
||||
|
||||
Iterable<Device> getDevices(ClientSession clientSessionOrNull);
|
||||
|
||||
-3
@@ -4,14 +4,11 @@ import com.igtimi.IgtimiStream.Msg;
|
||||
import com.mongodb.client.ClientSession;
|
||||
import com.sap.sailing.domain.igtimiadapter.DataAccessWindow;
|
||||
import com.sap.sailing.domain.igtimiadapter.Device;
|
||||
import com.sap.sailing.domain.igtimiadapter.Resource;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public interface MongoObjectFactory {
|
||||
void storeDevice(Device device, ClientSession clientSessionOrNull);
|
||||
void removeDevice(long deviceId, ClientSession clientSessionOrNull);
|
||||
void storeResource(Resource resource, ClientSession clientSessionOrNull);
|
||||
void removeResource(long resourceId, ClientSession clientSessionOrNull);
|
||||
void storeDataAccessWindow(DataAccessWindow daw, ClientSession clientSessionOrNull);
|
||||
void removeDataAccessWindow(long dawId, ClientSession clientSessionOrNull);
|
||||
|
||||
|
||||
-1
@@ -2,7 +2,6 @@ package com.sap.sailing.domain.igtimiadapter.persistence.impl;
|
||||
|
||||
public enum CollectionNames {
|
||||
IGTIMI_DEVICES,
|
||||
IGTIMI_RESOURCES,
|
||||
IGTIMI_DATA_ACCESS_WINDOWS,
|
||||
IGTIMI_MESSAGES;
|
||||
}
|
||||
|
||||
-22
@@ -25,7 +25,6 @@ import com.mongodb.client.MongoDatabase;
|
||||
import com.mongodb.client.model.Sorts;
|
||||
import com.sap.sailing.domain.igtimiadapter.DataAccessWindow;
|
||||
import com.sap.sailing.domain.igtimiadapter.Device;
|
||||
import com.sap.sailing.domain.igtimiadapter.Resource;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.DomainObjectFactory;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.TimeRange;
|
||||
@@ -42,27 +41,6 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
messagesCollection = MongoObjectFactoryImpl.getOrCreateMessagesCollection(db);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Resource> getResources(ClientSession clientSessionOrNull) {
|
||||
final List<Resource> result = new ArrayList<>();
|
||||
final MongoCollection<org.bson.Document> resourcesCollection = db.getCollection(CollectionNames.IGTIMI_RESOURCES.name());
|
||||
final FindIterable<Document> resourceDocuments =
|
||||
clientSessionOrNull == null ? resourcesCollection.find() : resourcesCollection.find(clientSessionOrNull);
|
||||
for (Object o : resourceDocuments) {
|
||||
final long id = ((Number) ((Document) o).get(FieldNames.IGTIMI_RESOURCES_ID.name())).longValue();
|
||||
final TimePoint startTime = getTimePoint((Document) o, FieldNames.IGTIMI_RESOURCES_START_TIME_MILLIS);
|
||||
final TimePoint endTime = getTimePoint((Document) o, FieldNames.IGTIMI_RESOURCES_END_TIME_MILLIS);
|
||||
final String deviceSerialNumber = (String) ((Document) o).get(FieldNames.IGTIMI_RESOURCES_DEVICE_SERIAL_NUMBER.name());
|
||||
final Integer[] dataTypesAsInteger = ((List<?>) ((Document) o).get(FieldNames.IGTIMI_RESOURCES_DATA_TYPES.name())).toArray(new Integer[0]);
|
||||
final int[] dataTypes = new int[dataTypesAsInteger.length];
|
||||
for (int i=0; i<dataTypesAsInteger.length; i++) {
|
||||
dataTypes[i] = dataTypesAsInteger[i];
|
||||
}
|
||||
result.add(Resource.create(id, startTime, endTime, deviceSerialNumber, dataTypes));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private TimePoint getTimePoint(Document o, final FieldNames timePointFieldName) {
|
||||
final Number startTimeMillisNumber = (Number) o.get(timePointFieldName.name());
|
||||
final TimePoint startTime = startTimeMillisNumber == null ? null : TimePoint.of(startTimeMillisNumber.longValue());
|
||||
|
||||
-1
@@ -2,7 +2,6 @@ package com.sap.sailing.domain.igtimiadapter.persistence.impl;
|
||||
|
||||
public enum FieldNames {
|
||||
IGTIMI_DEVICES_ID, IGTIMI_DEVICES_SERIAL_NUMBER, IGTIMI_DEVICES_NAME,
|
||||
IGTIMI_RESOURCES_ID, IGTIMI_RESOURCES_START_TIME_MILLIS, IGTIMI_RESOURCES_END_TIME_MILLIS, IGTIMI_RESOURCES_DEVICE_SERIAL_NUMBER, IGTIMI_RESOURCES_DATA_TYPES,
|
||||
IGTIMI_DATA_ACCESS_WINDOWS_ID, IGTIMI_DATA_ACCESS_WINDOWS_START_TIME_MILLIS, IGTIMI_DATA_ACCESS_WINDOWS_END_TIME_MILLIS, IGTIMI_DATA_ACCESS_WINDOWS_DEVICE_SERIAL_NUMBER,
|
||||
IGTIMI_MESSAGES_TIMESTAMP, IGTIMI_MESSAGES_DEVICE_SERIAL_NUMBER, IGTIMI_MESSAGES_PROTOBUF_MESSAGE;
|
||||
}
|
||||
|
||||
-32
@@ -18,7 +18,6 @@ import com.sap.sailing.domain.igtimiadapter.DataAccessWindow;
|
||||
import com.sap.sailing.domain.igtimiadapter.DataPointTimePointExtractor;
|
||||
import com.sap.sailing.domain.igtimiadapter.DataPointVisitor;
|
||||
import com.sap.sailing.domain.igtimiadapter.Device;
|
||||
import com.sap.sailing.domain.igtimiadapter.Resource;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.MongoObjectFactory;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
@@ -45,16 +44,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
@Override
|
||||
public void clear(ClientSession clientSessionOrNull) {
|
||||
final MongoCollection<Document> devicesCollection = db.getCollection(CollectionNames.IGTIMI_DEVICES.name()).withWriteConcern(WriteConcern.ACKNOWLEDGED);
|
||||
final MongoCollection<Document> resourcesCollection = db.getCollection(CollectionNames.IGTIMI_RESOURCES.name()).withWriteConcern(WriteConcern.ACKNOWLEDGED);
|
||||
final MongoCollection<Document> dataAccessWindowsCollections = db.getCollection(CollectionNames.IGTIMI_DATA_ACCESS_WINDOWS.name()).withWriteConcern(WriteConcern.ACKNOWLEDGED);
|
||||
if (clientSessionOrNull == null) {
|
||||
devicesCollection.drop();
|
||||
resourcesCollection.drop();
|
||||
dataAccessWindowsCollections.drop();
|
||||
messagesCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).drop();
|
||||
} else {
|
||||
devicesCollection.drop(clientSessionOrNull);
|
||||
resourcesCollection.drop(clientSessionOrNull);
|
||||
dataAccessWindowsCollections.drop(clientSessionOrNull);
|
||||
messagesCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).drop(clientSessionOrNull);
|
||||
}
|
||||
@@ -87,34 +83,6 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeResource(Resource resource, ClientSession clientSessionOrNull) {
|
||||
final Document filter = new Document(FieldNames.IGTIMI_RESOURCES_ID.name(), resource.getId());
|
||||
final Document update = new Document();
|
||||
update.put(FieldNames.IGTIMI_RESOURCES_ID.name(), resource.getId());
|
||||
update.put(FieldNames.IGTIMI_RESOURCES_DEVICE_SERIAL_NUMBER.name(), resource.getDeviceSerialNumber());
|
||||
update.put(FieldNames.IGTIMI_RESOURCES_START_TIME_MILLIS.name(), resource.getStartTime() == null ? null : resource.getStartTime().asMillis());
|
||||
update.put(FieldNames.IGTIMI_RESOURCES_END_TIME_MILLIS.name(), resource.getEndTime() == null ? null : resource.getEndTime().asMillis());
|
||||
update.put(FieldNames.IGTIMI_RESOURCES_DATA_TYPES.name(), Util.asList(Util.map(resource.getDataTypes(), dataType->dataType.getCode())));
|
||||
final MongoCollection<Document> resourcesCollection = db.getCollection(CollectionNames.IGTIMI_RESOURCES.name()).withWriteConcern(WriteConcern.ACKNOWLEDGED);
|
||||
if (clientSessionOrNull == null) {
|
||||
resourcesCollection.replaceOne(filter, update, new ReplaceOptions().upsert(true));
|
||||
} else {
|
||||
resourcesCollection.replaceOne(clientSessionOrNull, filter, update, new ReplaceOptions().upsert(true));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeResource(long resourceId, ClientSession clientSessionOrNull) {
|
||||
final Document filter = new Document(FieldNames.IGTIMI_DEVICES_ID.name(), resourceId);
|
||||
final MongoCollection<Document> resourcesCollection = db.getCollection(CollectionNames.IGTIMI_RESOURCES.name()).withWriteConcern(WriteConcern.ACKNOWLEDGED);
|
||||
if (clientSessionOrNull == null) {
|
||||
resourcesCollection.deleteOne(filter);
|
||||
} else {
|
||||
resourcesCollection.deleteOne(clientSessionOrNull, filter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeDataAccessWindow(DataAccessWindow daw, ClientSession clientSessionOrNull) {
|
||||
final Document filter = new Document(FieldNames.IGTIMI_DATA_ACCESS_WINDOWS_ID.name(), daw.getId());
|
||||
|
||||
-5
@@ -11,7 +11,6 @@ import org.osgi.framework.BundleContext;
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sailing.domain.igtimiadapter.DataAccessWindow;
|
||||
import com.sap.sailing.domain.igtimiadapter.Device;
|
||||
import com.sap.sailing.domain.igtimiadapter.Resource;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.DomainObjectFactory;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.MongoObjectFactory;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.PersistenceFactory;
|
||||
@@ -72,9 +71,6 @@ public class Activator implements BundleActivator {
|
||||
securityServiceServiceTracker = FullyInitializedReplicableTracker.createAndOpen(context, SecurityService.class);
|
||||
try {
|
||||
final SecurityService securityService = securityServiceServiceTracker.getInitializedService(0);
|
||||
for (Resource resource : riotServer.getResources()) {
|
||||
securityService.migrateOwnership(resource);
|
||||
}
|
||||
for (DataAccessWindow daw : riotServer.getDataAccessWindows()) {
|
||||
securityService.migrateOwnership(daw);
|
||||
}
|
||||
@@ -86,7 +82,6 @@ public class Activator implements BundleActivator {
|
||||
securityService.assumeOwnershipMigrated(igtimiAccountTypeName);
|
||||
securityService.assumeOwnershipMigrated(SecuredDomainType.IGTIMI_DATA_ACCESS_WINDOW.getName());
|
||||
securityService.assumeOwnershipMigrated(SecuredDomainType.IGTIMI_DEVICE.getName());
|
||||
securityService.assumeOwnershipMigrated(SecuredDomainType.IGTIMI_RESOURCE.getName());
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Error trying to create missing ownerships for Igtimi entities", e);
|
||||
}
|
||||
|
||||
+1
-8
@@ -3,23 +3,16 @@ package com.sap.sailing.domain.igtimiadapter.server.replication;
|
||||
import com.igtimi.IgtimiStream.Msg;
|
||||
import com.sap.sailing.domain.igtimiadapter.DataAccessWindow;
|
||||
import com.sap.sailing.domain.igtimiadapter.Device;
|
||||
import com.sap.sailing.domain.igtimiadapter.Resource;
|
||||
import com.sap.sailing.domain.igtimiadapter.server.riot.RiotServer;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public interface ReplicableRiotServer extends RiotServer {
|
||||
|
||||
Void internalAddDevice(Device device);
|
||||
|
||||
Void internalRemoveDevice(long deviceId);
|
||||
|
||||
Void internalUpdateDeviceName(long deviceId, String name);
|
||||
|
||||
Void internalAddResource(Resource resource);
|
||||
|
||||
Void internalRemoveResource(long resourceId);
|
||||
|
||||
DataAccessWindow internalAddDataAccessWindow(String deviceSerialNumber, TimePoint startTime, TimePoint endTime);
|
||||
DataAccessWindow internalCreateDataAccessWindow(String deviceSerialNumber, TimePoint startTime, TimePoint endTime);
|
||||
|
||||
Void internalRemoveDataAccessWindow(long dawId);
|
||||
|
||||
|
||||
-11
@@ -19,7 +19,6 @@ import com.sap.sailing.domain.igtimiadapter.Device;
|
||||
import com.sap.sailing.domain.igtimiadapter.FixFactory;
|
||||
import com.sap.sailing.domain.igtimiadapter.IgtimiConnection;
|
||||
import com.sap.sailing.domain.igtimiadapter.IgtimiWindListener;
|
||||
import com.sap.sailing.domain.igtimiadapter.Resource;
|
||||
import com.sap.sailing.domain.igtimiadapter.datatypes.Fix;
|
||||
import com.sap.sailing.domain.igtimiadapter.datatypes.Type;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.DomainObjectFactory;
|
||||
@@ -91,14 +90,6 @@ public interface RiotServer extends Replicable<ReplicableRiotServer, RiotReplica
|
||||
*/
|
||||
int getPort() throws IOException;
|
||||
|
||||
Iterable<Resource> getResources();
|
||||
|
||||
Resource getResourceById(long id);
|
||||
|
||||
void addResource(Resource resource);
|
||||
|
||||
void removeResource(long resourceId);
|
||||
|
||||
Iterable<Device> getDevices();
|
||||
|
||||
Device getDeviceById(long id);
|
||||
@@ -110,8 +101,6 @@ public interface RiotServer extends Replicable<ReplicableRiotServer, RiotReplica
|
||||
*/
|
||||
Device createDevice(String deviceSerialNumber);
|
||||
|
||||
void addDevice(Device device);
|
||||
|
||||
void removeDevice(long deviceId);
|
||||
|
||||
void updateDeviceName(long deviceId, String name);
|
||||
|
||||
+4
-58
@@ -40,7 +40,6 @@ import com.sap.sailing.domain.igtimiadapter.DataPointVisitor;
|
||||
import com.sap.sailing.domain.igtimiadapter.Device;
|
||||
import com.sap.sailing.domain.igtimiadapter.IgtimiConnection;
|
||||
import com.sap.sailing.domain.igtimiadapter.IgtimiConnectionFactory;
|
||||
import com.sap.sailing.domain.igtimiadapter.Resource;
|
||||
import com.sap.sailing.domain.igtimiadapter.datatypes.Type;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.DomainObjectFactory;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.MongoObjectFactory;
|
||||
@@ -69,7 +68,6 @@ import com.sap.sse.util.ObjectInputStreamResolvingAgainstCache;
|
||||
public class RiotServerImpl extends AbstractReplicableWithObjectInputStream<ReplicableRiotServer, RiotReplicationOperation<?>> implements RiotServer, ReplicableRiotServer, Runnable {
|
||||
private static final Logger logger = Logger.getLogger(RiotServerImpl.class.getName());
|
||||
|
||||
private final ConcurrentMap<Long, Resource> resources;
|
||||
private final ConcurrentMap<Long, DataAccessWindow> dataAccessWindows;
|
||||
private final ConcurrentMap<Long, Device> devices;
|
||||
private final ConcurrentMap<String, Device> devicesBySerialNumber;
|
||||
@@ -109,7 +107,6 @@ public class RiotServerImpl extends AbstractReplicableWithObjectInputStream<Repl
|
||||
public RiotServerImpl(SocketAddress localAddress, DomainObjectFactory domainObjectFactory,
|
||||
MongoObjectFactory mongoObjectFactory) throws Exception {
|
||||
this.listeners = ConcurrentHashMap.newKeySet();
|
||||
this.resources = new ConcurrentHashMap<>();
|
||||
this.dataAccessWindows = new ConcurrentHashMap<>();
|
||||
this.devices = new ConcurrentHashMap<>();
|
||||
this.devicesBySerialNumber = new ConcurrentHashMap<>();
|
||||
@@ -121,9 +118,6 @@ public class RiotServerImpl extends AbstractReplicableWithObjectInputStream<Repl
|
||||
devices.put(device.getId(), device);
|
||||
devicesBySerialNumber.put(device.getSerialNumber(), device);
|
||||
}
|
||||
for (final Resource resource : domainObjectFactory.getResources(/* clientSessionOrNull */ null)) {
|
||||
resources.put(resource.getId(), resource);
|
||||
}
|
||||
for (final DataAccessWindow daw : domainObjectFactory.getDataAccessWindows(/* clientSessionOrNull */ null)) {
|
||||
dataAccessWindows.put(daw.getId(), daw);
|
||||
}
|
||||
@@ -368,21 +362,10 @@ public class RiotServerImpl extends AbstractReplicableWithObjectInputStream<Repl
|
||||
public Device internalCreateDevice(String deviceSerialNumber) {
|
||||
final long id = devices.isEmpty() ? 1 : Collections.max(devices.keySet()) + 1;
|
||||
final Device device = Device.create(id, deviceSerialNumber);
|
||||
internalAddDevice(device);
|
||||
return device;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDevice(Device device) {
|
||||
apply(s->s.internalAddDevice(device));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void internalAddDevice(Device device) {
|
||||
devices.put(device.getId(), device);
|
||||
devicesBySerialNumber.put(device.getSerialNumber(), device);
|
||||
mongoObjectFactory.storeDevice(device, /* clientSessionOrNull */ null);
|
||||
return null;
|
||||
return device;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -413,40 +396,6 @@ public class RiotServerImpl extends AbstractReplicableWithObjectInputStream<Repl
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Resource> getResources() {
|
||||
return Collections.unmodifiableCollection(resources.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource getResourceById(long id) {
|
||||
return resources.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResource(Resource resource) {
|
||||
apply(s->s.internalAddResource(resource));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void internalAddResource(Resource resource) {
|
||||
resources.put(resource.getId(), resource);
|
||||
mongoObjectFactory.storeResource(resource, /* clientSessionOrNull */ null);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeResource(long resourceId) {
|
||||
apply(s->s.internalRemoveResource(resourceId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void internalRemoveResource(long resourceId) {
|
||||
resources.remove(resourceId);
|
||||
mongoObjectFactory.removeResource(resourceId, /* clientSessionOrNull */ null);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<DataAccessWindow> getDataAccessWindows() {
|
||||
return Collections.unmodifiableCollection(dataAccessWindows.values());
|
||||
@@ -460,7 +409,7 @@ public class RiotServerImpl extends AbstractReplicableWithObjectInputStream<Repl
|
||||
@Override
|
||||
public Iterable<DataAccessWindow> getDataAccessWindows(Iterable<String> deviceSerialNumbers, TimeRange timeRange) {
|
||||
final Set<DataAccessWindow> result = new HashSet<>();
|
||||
final Set<String> deviceSerialNumbersAsSet = new HashSet<>();
|
||||
final Set<String> deviceSerialNumbersAsSet = Util.asSet(deviceSerialNumbers);
|
||||
// TODO provide a more efficient implementation if this turns out to become a performance bottleneck, e.g., by keeping the DataAccessWindows in a time-sorted TreeSet
|
||||
for (final DataAccessWindow daw : getDataAccessWindows()) {
|
||||
if (deviceSerialNumbersAsSet.contains(daw.getDeviceSerialNumber()) && timeRange.intersects(daw.getTimeRange())) {
|
||||
@@ -472,11 +421,11 @@ public class RiotServerImpl extends AbstractReplicableWithObjectInputStream<Repl
|
||||
|
||||
@Override
|
||||
public DataAccessWindow createDataAccessWindow(String deviceSerialNumber, TimePoint from, TimePoint to) {
|
||||
return apply(s->s.internalAddDataAccessWindow(deviceSerialNumber, from, to));
|
||||
return apply(s->s.internalCreateDataAccessWindow(deviceSerialNumber, from, to));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataAccessWindow internalAddDataAccessWindow(String deviceSerialNumber, TimePoint from, TimePoint to) {
|
||||
public DataAccessWindow internalCreateDataAccessWindow(String deviceSerialNumber, TimePoint from, TimePoint to) {
|
||||
final long newId = dataAccessWindows.isEmpty() ? 1 : Collections.max(dataAccessWindows.keySet()) + 1;
|
||||
final DataAccessWindow daw = DataAccessWindow.create(newId, from, to, deviceSerialNumber);
|
||||
dataAccessWindows.put(daw.getId(), daw);
|
||||
@@ -503,7 +452,6 @@ public class RiotServerImpl extends AbstractReplicableWithObjectInputStream<Repl
|
||||
public void clear() {
|
||||
devices.clear();
|
||||
devicesBySerialNumber.clear();
|
||||
resources.clear();
|
||||
dataAccessWindows.clear();
|
||||
connections.clear();
|
||||
listeners.clear();
|
||||
@@ -530,14 +478,12 @@ public class RiotServerImpl extends AbstractReplicableWithObjectInputStream<Repl
|
||||
for (final Device device : devices.values()) {
|
||||
devicesBySerialNumber.put(device.getSerialNumber(), device);
|
||||
}
|
||||
resources.putAll((Map<Long, Resource>) is.readObject());
|
||||
dataAccessWindows.putAll((Map<Long, DataAccessWindow>) is.readObject());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeForInitialReplicationInternal(ObjectOutputStream objectOutputStream) throws IOException {
|
||||
objectOutputStream.writeObject(new HashMap<>(devices));
|
||||
objectOutputStream.writeObject(new HashMap<>(resources));
|
||||
objectOutputStream.writeObject(new HashMap<>(dataAccessWindows));
|
||||
}
|
||||
|
||||
|
||||
BIN
Binary file not shown.
-16
@@ -23,7 +23,6 @@ import com.igtimi.IgtimiStream.Msg;
|
||||
import com.mongodb.client.ClientSession;
|
||||
import com.sap.sailing.domain.igtimiadapter.DataAccessWindow;
|
||||
import com.sap.sailing.domain.igtimiadapter.Device;
|
||||
import com.sap.sailing.domain.igtimiadapter.Resource;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.TimeRange;
|
||||
@@ -67,21 +66,6 @@ public class IgtimiPersistenceTest {
|
||||
assertEquals(device.getSerialNumber(), loadedDevice.getSerialNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoringAndLoadingSimpleResource() {
|
||||
final TimePoint from = TimePoint.now();
|
||||
final TimePoint to = from.plus(Duration.ONE_MINUTE);
|
||||
final Resource resource = Resource.create(234, from, to, "AA-DE-AACC", new int[] { 1, 4, 7 });
|
||||
mongoObjectFactory.storeResource(resource, clientSession);
|
||||
final Resource loadedResource = domainObjectFactory.getResources(clientSession).iterator().next();
|
||||
assertEquals(resource.getId(), loadedResource.getId());
|
||||
assertEquals(resource.getName(), loadedResource.getName()); // an inferred value; still useful to compare
|
||||
assertEquals(resource.getStartTime(), loadedResource.getStartTime());
|
||||
assertEquals(resource.getEndTime(), loadedResource.getEndTime());
|
||||
assertEquals(resource.getDeviceSerialNumber(), loadedResource.getDeviceSerialNumber());
|
||||
assertEquals(Util.asSet(resource.getDataTypes()), Util.asSet(loadedResource.getDataTypes()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoringAndLoadingSimpleDataAccessWindow() {
|
||||
final TimePoint from = TimePoint.now();
|
||||
|
||||
+4
-18
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.domain.igtimiadapter.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
@@ -24,12 +25,14 @@ public class TestSimpleProtobufReading {
|
||||
final InputStream is = getClass().getResourceAsStream("/windbot_session_20250107.base64");
|
||||
final BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
||||
String base64;
|
||||
int messageCount = 0;
|
||||
while ((base64=br.readLine()) != null) {
|
||||
final Msg msg = Msg.parseFrom(Base64.decode(base64));
|
||||
assertNotNull(msg);
|
||||
logger.info(String.format("Parsed the following message:\n %s", msg.toString()));
|
||||
messageCount++;
|
||||
}
|
||||
is.close();
|
||||
assertEquals(17920, messageCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -65,21 +68,4 @@ public class TestSimpleProtobufReading {
|
||||
}
|
||||
is.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadSAPWindbotStartup() throws IOException {
|
||||
final InputStream is = getClass().getResourceAsStream("/windbot_wdf53_20250107_2.protobuf");
|
||||
final ExtensionRegistry er = ExtensionRegistry.newInstance();
|
||||
final CodedInputStream cis = CodedInputStream.newInstance(is);
|
||||
for (int i=0; i<20; i++) { // we know there are four full messages in the stream:
|
||||
final int lengthOfMessage = cis.readRawVarint32();
|
||||
assertNotEquals(0, lengthOfMessage);
|
||||
final int oldLimit = cis.pushLimit(lengthOfMessage);
|
||||
final Msg msg = Msg.parseFrom(cis, er);
|
||||
assertNotNull(msg);
|
||||
logger.info(String.format("Parsed the following message #%d:\n %s", i, msg.toString()));
|
||||
cis.popLimit(oldLimit);
|
||||
}
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -3,5 +3,8 @@ package com.sap.sailing.domain.igtimiadapter;
|
||||
import java.io.Serializable;
|
||||
|
||||
public interface HasId extends Serializable {
|
||||
/**
|
||||
* 0 is not a valid ID but is used as a marker to ask for an auto-generated ID
|
||||
*/
|
||||
long getId();
|
||||
}
|
||||
|
||||
-24
@@ -27,21 +27,6 @@ import com.sap.sse.security.shared.HasPermissions.DefaultActions;
|
||||
* @author Axel Uhl (d043530)
|
||||
*/
|
||||
public interface IgtimiConnection {
|
||||
/**
|
||||
* @param startTime
|
||||
* optional; may be <code>null</code>
|
||||
* @param endTime
|
||||
* optional; may be <code>null</code>
|
||||
* @param deviceIds
|
||||
* optional (may be <code>null</code>) if <code>permission</code> is {@link Permission#modify}; lists the
|
||||
* devices for which to look for resources
|
||||
* @param streamIds
|
||||
* optional; may be <code>null</code>
|
||||
*/
|
||||
Iterable<Resource> getResources(Permission permission, TimePoint startTime, TimePoint endTime,
|
||||
Iterable<String> deviceIds, Iterable<String> streamIds) throws IllegalStateException,
|
||||
ClientProtocolException, IOException, ParseException;
|
||||
|
||||
/**
|
||||
* All arguments are mandatory.
|
||||
*
|
||||
@@ -72,15 +57,6 @@ public interface IgtimiConnection {
|
||||
*/
|
||||
Iterable<Msg> getMessages(TimePoint startTime, TimePoint endTime, Iterable<String> deviceSerialNumbers, Type[] types) throws IllegalStateException, ClientProtocolException, IOException, ParseException;
|
||||
|
||||
/**
|
||||
* Shorthand for {@link #getResourceData(TimePoint, TimePoint, Iterable, Map)} where no compression is requested for
|
||||
* any type. The fixes received are forwarded to the {@link BulkFixReceiver} <code>bulkFixReceiver</code> in one call.
|
||||
*/
|
||||
Iterable<Fix> getAndNotifyResourceData(TimePoint startTime, TimePoint endTime,
|
||||
Iterable<String> deviceSerialNumbers, BulkFixReceiver bulkFixReceiver, Type... types)
|
||||
throws IllegalStateException, ClientProtocolException, IOException, ParseException;
|
||||
|
||||
|
||||
/**
|
||||
* Same as {@link #getResourceData(TimePoint, TimePoint, Iterable, Type...)}, but the resulting {@link Fix}es are
|
||||
* grouped into {@link Track}s per fix type and per device.
|
||||
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
package com.sap.sailing.domain.igtimiadapter;
|
||||
|
||||
import com.sap.sailing.domain.igtimiadapter.datatypes.Type;
|
||||
import com.sap.sailing.domain.igtimiadapter.impl.ResourceImpl;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.security.shared.WithQualifiedObjectIdentifier;
|
||||
|
||||
|
||||
/**
|
||||
* You can think of resources really as meta-info - identifying time blocks of data that have some meaning. For an
|
||||
* Igtimi device it's a power cycle. However data access is not forced to be "through" a resource. If you only wanted to
|
||||
* get data from a specific resource then of course you would just use the start and end time stamps in the request.
|
||||
* Resources are meant to be non-overlapping, although this is not strictly enforced.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public interface Resource extends HasId, HasStartAndEndTime, WithQualifiedObjectIdentifier {
|
||||
Iterable<Type> getDataTypes();
|
||||
|
||||
String getDeviceSerialNumber();
|
||||
|
||||
static Resource create(long id, TimePoint startTime, TimePoint endTime, String deviceSerialNumber, int[] dataTypes) {
|
||||
return new ResourceImpl(id, startTime, endTime, deviceSerialNumber, dataTypes);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -12,7 +12,7 @@ public class DataAccessWindowDeserializer {
|
||||
static final String DEVICE_SERIAL_NUMBER = "device_serial_number";
|
||||
|
||||
public DataAccessWindow createDataAccessWindowFromJson(JSONObject resourceJson) {
|
||||
return new DataAccessWindowImpl((Long) resourceJson.get(ID),
|
||||
return new DataAccessWindowImpl((Long) resourceJson.getOrDefault(ID, 0),
|
||||
new MillisecondsTimePoint(((Number) resourceJson.get(START_TIME)).longValue()),
|
||||
new MillisecondsTimePoint(((Number) resourceJson.get(END_TIME)).longValue()),
|
||||
(String) resourceJson.get(DEVICE_SERIAL_NUMBER));
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ public class DeviceDeserializer {
|
||||
static final String NAME = "name";
|
||||
|
||||
public Device createDeviceFromJson(JSONObject deviceJson) {
|
||||
return new DeviceImpl((Long) deviceJson.get(ID), (String) deviceJson.get(SERIAL_NUMBER),
|
||||
return new DeviceImpl((Long) deviceJson.getOrDefault(ID, 0), (String) deviceJson.get(SERIAL_NUMBER),
|
||||
(String) deviceJson.get(NAME));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ public class DeviceImpl extends HasIdImpl implements Device {
|
||||
this(id, serialNumber, /* name */ null);
|
||||
}
|
||||
|
||||
public DeviceImpl(Long id, String serialNumber, String name) {
|
||||
public DeviceImpl(long id, String serialNumber, String name) {
|
||||
super(id);
|
||||
this.serialNumber = serialNumber;
|
||||
this.name = name;
|
||||
|
||||
+8
-78
@@ -37,7 +37,6 @@ import com.sap.sailing.domain.igtimiadapter.FixFactory;
|
||||
import com.sap.sailing.domain.igtimiadapter.IgtimiConnection;
|
||||
import com.sap.sailing.domain.igtimiadapter.LiveDataConnection;
|
||||
import com.sap.sailing.domain.igtimiadapter.Permission;
|
||||
import com.sap.sailing.domain.igtimiadapter.Resource;
|
||||
import com.sap.sailing.domain.igtimiadapter.datatypes.Fix;
|
||||
import com.sap.sailing.domain.igtimiadapter.datatypes.Type;
|
||||
import com.sap.sailing.domain.igtimiadapter.shared.IgtimiWindReceiver;
|
||||
@@ -75,19 +74,6 @@ public class IgtimiConnectionImpl extends SecuredServerImpl implements IgtimiCon
|
||||
liveDataConnectionFactory = new LiveDataConnectionFactoryImpl(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Resource> getResources(Permission permission, TimePoint startTime, TimePoint endTime,
|
||||
Iterable<String> deviceIds, Iterable<String> streamIds) throws IllegalStateException, ClientProtocolException, IOException, ParseException {
|
||||
final HttpGet getResources = new HttpGet(getResourcesUrl(permission, startTime, endTime, deviceIds, streamIds));
|
||||
final JSONObject resourcesJson = (JSONObject) getJsonParsedResponse(getResources).getA();
|
||||
final List<Resource> result = new ArrayList<>();
|
||||
for (Object resourceJson : (JSONArray) resourcesJson.get("resources")) {
|
||||
Resource resource = new ResourceDeserializer().createResourceFromJson((JSONObject) ((JSONObject) resourceJson).get("resource"));
|
||||
result.add(resource);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Fix> getLatestFixes(Iterable<String> deviceSerialNumbers, Type type) throws IllegalStateException, ClientProtocolException, IOException, ParseException {
|
||||
final HttpGet getLatestData = new HttpGet(getLatestDatumUrl(deviceSerialNumbers, type));
|
||||
@@ -191,8 +177,11 @@ public class IgtimiConnectionImpl extends SecuredServerImpl implements IgtimiCon
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Fix> getAndNotifyResourceData(TimePoint startTime, TimePoint endTime,
|
||||
/**
|
||||
* Shorthand for {@link #getResourceData(TimePoint, TimePoint, Iterable, Map)} where no compression is requested for
|
||||
* any type. The fixes received are forwarded to the {@link BulkFixReceiver} <code>bulkFixReceiver</code> in one call.
|
||||
*/
|
||||
private Iterable<Fix> getAndNotifyResourceData(TimePoint startTime, TimePoint endTime,
|
||||
Iterable<String> deviceSerialNumbers, BulkFixReceiver bulkFixReceiver, Type... types)
|
||||
throws IllegalStateException, ClientProtocolException, IOException, ParseException {
|
||||
Iterable<Fix> result = getResourceData(startTime, endTime, deviceSerialNumbers, types);
|
||||
@@ -307,29 +296,9 @@ public class IgtimiConnectionImpl extends SecuredServerImpl implements IgtimiCon
|
||||
final TimePoint receivingEndTime = IgtimiWindTracker.getReceivingEndTime(trackedRace);
|
||||
endOfWindow = Collections.max(Arrays.asList(endOfWindow, receivingEndTime==null?MillisecondsTimePoint.now():receivingEndTime));
|
||||
}
|
||||
Iterable<DataAccessWindow> daws = getDataAccessWindows(Permission.read, startOfWindow, endOfWindow, /* find all deviceSerialNumbers for window */ null);
|
||||
logger.info("Found "+Util.size(daws)+" data access windows. Analyzing which ones contain wind data...");
|
||||
Set<String> deviceSerialNumbers = new HashSet<>();
|
||||
for (DataAccessWindow daw : daws) {
|
||||
String deviceSerialNumber = daw.getDeviceSerialNumber();
|
||||
// now filter for the wind-providing devices
|
||||
Iterable<Resource> resources = getResources(Permission.read, startOfWindow, endOfWindow,
|
||||
Collections.singleton(deviceSerialNumber), /* streamIds */ null);
|
||||
if (hasWind(resources)) {
|
||||
StringBuilder resourceIDs = new StringBuilder();
|
||||
boolean first = true;
|
||||
for (Resource resource : resources) {
|
||||
if (!first) {
|
||||
resourceIDs.append(", ");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
resourceIDs.append(resource.getId());
|
||||
}
|
||||
logger.info(" Resources ["+resourceIDs+"] for device "+deviceSerialNumber+" contain wind data");
|
||||
deviceSerialNumbers.add(deviceSerialNumber);
|
||||
}
|
||||
}
|
||||
final Iterable<DataAccessWindow> daws = getDataAccessWindows(Permission.read, startOfWindow, endOfWindow, /* find all deviceSerialNumbers for window */ null);
|
||||
logger.info("Found "+Util.size(daws)+" data access windows.");
|
||||
final Set<String> deviceSerialNumbers = Util.asSet(Util.map(daws, DataAccessWindow::getDeviceSerialNumber));
|
||||
final Map<TrackedRace, Integer> result;
|
||||
if (!deviceSerialNumbers.isEmpty()) {
|
||||
IgtimiWindReceiver windReceiver = new IgtimiWindReceiver(correctByDeclination ? DeclinationService.INSTANCE : null);
|
||||
@@ -347,15 +316,6 @@ public class IgtimiConnectionImpl extends SecuredServerImpl implements IgtimiCon
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean hasWind(Iterable<Resource> resources) {
|
||||
for (Resource resource : resources) {
|
||||
if (Util.contains(resource.getDataTypes(), Type.AWS)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> getWindDevices() throws IllegalStateException, ClientProtocolException, IOException, ParseException {
|
||||
// find all the devices from which we may read
|
||||
@@ -475,36 +435,6 @@ public class IgtimiConnectionImpl extends SecuredServerImpl implements IgtimiCon
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
private String getResourcesUrl(Permission permission, TimePoint startTime, TimePoint endTime,
|
||||
Iterable<String> serialNumbers, Iterable<String> streamIds) {
|
||||
final StringBuilder url = new StringBuilder(getApiV1BaseUrl());
|
||||
url.append("resources?");
|
||||
url.append("permission=");
|
||||
url.append(permission.name());
|
||||
if (startTime != null) {
|
||||
url.append("&start_time=");
|
||||
url.append(startTime.asMillis());
|
||||
}
|
||||
if (endTime != null) {
|
||||
url.append("&end_time=");
|
||||
url.append(endTime.asMillis());
|
||||
}
|
||||
if (serialNumbers != null) {
|
||||
for (String serialNumber : serialNumbers) {
|
||||
url.append("&serial_numbers[]=");
|
||||
url.append(serialNumber);
|
||||
}
|
||||
}
|
||||
if (streamIds != null) {
|
||||
for (String streamId : streamIds) {
|
||||
url.append("&stream_ids[]=");
|
||||
url.append(streamId);
|
||||
}
|
||||
}
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterable<URI> getWebsocketServers() throws IllegalStateException, ClientProtocolException, IOException, ParseException, URISyntaxException {
|
||||
final HttpGet getWebsocketServers = new HttpGet(getApiV1BaseUrl()+"server_listers/web_sockets");
|
||||
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
package com.sap.sailing.domain.igtimiadapter.impl;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import com.sap.sailing.domain.igtimiadapter.Resource;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class ResourceDeserializer {
|
||||
static final String ID = "id";
|
||||
static final String START_TIME = "start_time";
|
||||
static final String END_TIME = "end_time";
|
||||
static final String DEVICE_SERIAL_NUMBER = "device_serial_number";
|
||||
static final String DATA_TYPES = "data_types";
|
||||
|
||||
public Resource createResourceFromJson(JSONObject resourceJson) {
|
||||
return new ResourceImpl((Long) resourceJson.get(ID),
|
||||
resourceJson.get(START_TIME)==null?null:new MillisecondsTimePoint(((Number) resourceJson.get(START_TIME)).longValue()),
|
||||
resourceJson.get(END_TIME)==null?null:new MillisecondsTimePoint(((Number) resourceJson.get(END_TIME)).longValue()),
|
||||
(String) resourceJson.get(DEVICE_SERIAL_NUMBER),
|
||||
getDataTypes((JSONArray) resourceJson.get(DATA_TYPES)));
|
||||
}
|
||||
|
||||
private int[] getDataTypes(JSONArray jsonArray) {
|
||||
final int[] result = new int[jsonArray.size()];
|
||||
int i=0;
|
||||
for (Object o : jsonArray) {
|
||||
result[i++] = ((Long) o).intValue();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
package com.sap.sailing.domain.igtimiadapter.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sailing.domain.igtimiadapter.Resource;
|
||||
import com.sap.sailing.domain.igtimiadapter.datatypes.Type;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.security.shared.HasPermissions;
|
||||
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
|
||||
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
|
||||
|
||||
public class ResourceImpl implements Resource {
|
||||
private static final long serialVersionUID = -8944469021862963744L;
|
||||
private final long id;
|
||||
private final TimePoint startTime;
|
||||
private final TimePoint endTime;
|
||||
private final String deviceSerialNumber;
|
||||
private final int[] dataTypes;
|
||||
|
||||
public ResourceImpl(long id, TimePoint startTime, TimePoint endTime, String deviceSerialNumber, int[] dataTypes) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.startTime = startTime;
|
||||
this.endTime = endTime;
|
||||
this.deviceSerialNumber = deviceSerialNumber;
|
||||
this.dataTypes = dataTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimePoint getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimePoint getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeviceSerialNumber() {
|
||||
return deviceSerialNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Type> getDataTypes() {
|
||||
List<Type> result = new ArrayList<Type>();
|
||||
for (int dataType : dataTypes) {
|
||||
result.add(Type.valueOf(dataType));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QualifiedObjectIdentifier getIdentifier() {
|
||||
return getPermissionType().getQualifiedObjectIdentifier(new TypeRelativeObjectIdentifier(""+getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public HasPermissions getPermissionType() {
|
||||
return SecuredDomainType.IGTIMI_RESOURCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Igtimi Resource "+getId();
|
||||
}
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
package com.sap.sailing.domain.igtimiadapter.impl;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import com.sap.sailing.domain.igtimiadapter.Resource;
|
||||
import com.sap.sailing.domain.igtimiadapter.datatypes.Type;
|
||||
|
||||
public class ResourceSerializer {
|
||||
public JSONObject createJsonFromResource(Resource resource) {
|
||||
final JSONObject resourceJson = new JSONObject();
|
||||
resourceJson.put(ResourceDeserializer.ID, resource.getId());
|
||||
resourceJson.put(ResourceDeserializer.START_TIME, resource.getStartTime()==null?null:resource.getStartTime().asMillis());
|
||||
resourceJson.put(ResourceDeserializer.END_TIME, resource.getEndTime()==null?null:resource.getEndTime().asMillis());
|
||||
resourceJson.put(ResourceDeserializer.DEVICE_SERIAL_NUMBER, resource.getDeviceSerialNumber());
|
||||
final JSONArray dataTypesJson = new JSONArray();
|
||||
for (final Type dataType : resource.getDataTypes()) {
|
||||
dataTypesJson.add(dataType.getCode());
|
||||
}
|
||||
resourceJson.put(ResourceDeserializer.DATA_TYPES, dataTypesJson);
|
||||
return resourceJson;
|
||||
}
|
||||
}
|
||||
+7
-2
@@ -3,23 +3,25 @@ package com.sap.sailing.selenium.api.test;
|
||||
import static com.sap.sailing.selenium.api.core.ApiContext.SHARED_SERVER_CONTEXT;
|
||||
import static com.sap.sailing.selenium.api.core.ApiContext.createAdminApiContext;
|
||||
|
||||
import com.google.protobuf.CodedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.URL;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.Timeout;
|
||||
|
||||
import com.google.protobuf.CodedOutputStream;
|
||||
import com.sap.sailing.domain.igtimiadapter.IgtimiConnection;
|
||||
import com.sap.sailing.domain.igtimiadapter.IgtimiConnectionFactory;
|
||||
import com.sap.sailing.selenium.api.core.ApiContext;
|
||||
import com.sap.sailing.selenium.api.core.Authenticator;
|
||||
import com.sap.sailing.selenium.test.AbstractSeleniumTest;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sun.jersey.core.util.Base64;
|
||||
|
||||
/**
|
||||
@@ -68,7 +70,10 @@ public class AbstractTestWithIgtimiConnection extends AbstractSeleniumTest {
|
||||
cos.flush();
|
||||
sos.close();
|
||||
socket.close();
|
||||
// TODO do we need to wait until the data has been received and processed?
|
||||
final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
|
||||
connection.createDataAccessWindow("DC-GD-AAED",
|
||||
TimePoint.of(df.parse("2025-01-07T08:00:00Z")),
|
||||
TimePoint.of(df.parse("2025-01-07T22:00:00Z")));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
+21
-34
@@ -21,7 +21,6 @@ import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.igtimiadapter.DataAccessWindow;
|
||||
import com.sap.sailing.domain.igtimiadapter.Permission;
|
||||
import com.sap.sailing.domain.igtimiadapter.Resource;
|
||||
import com.sap.sailing.domain.igtimiadapter.datatypes.AWA;
|
||||
import com.sap.sailing.domain.igtimiadapter.datatypes.AWS;
|
||||
import com.sap.sailing.domain.igtimiadapter.datatypes.Fix;
|
||||
@@ -30,18 +29,15 @@ import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
// TODO This needs to become a Selenium test with the OSGi product and the igtimiadapter.gateway bundle running.
|
||||
// TODO Furthermore, the test assumes specific data to be present in some Riot server to test against; is this a good idea?
|
||||
// TODO If so, we would need to ensure that the data against which to test is actually present in the Riot test server...
|
||||
public class BasicIgtimiAdapterTest extends AbstractTestWithIgtimiConnection {
|
||||
@Test
|
||||
public void testGetDataAccessWindows() throws ClientProtocolException, IllegalStateException, IOException, ParseException {
|
||||
Iterable<DataAccessWindow> daws = connection.getDataAccessWindows(Permission.read, /* startTime */ null,
|
||||
/* endTime */ null, /* deviceSerialNumbers */ Collections.singleton("DD-EE-AAGA"));
|
||||
/* endTime */ null, /* deviceSerialNumbers */ Collections.singleton("DC-GD-AAED"));
|
||||
assertFalse(Util.isEmpty(daws));
|
||||
for (DataAccessWindow daw : daws) {
|
||||
assertEquals("DD-EE-AAGA", daw.getDeviceSerialNumber());
|
||||
assertTrue(daw.getId() == 17012);
|
||||
assertEquals("DC-GD-AAED", daw.getDeviceSerialNumber());
|
||||
assertTrue(daw.getId() == 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,27 +49,22 @@ public class BasicIgtimiAdapterTest extends AbstractTestWithIgtimiConnection {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetResources() throws ClientProtocolException, IllegalStateException, IOException, ParseException {
|
||||
Iterable<Resource> resources = connection.getResources(Permission.read, /* start time */ null, /* end time */ null,
|
||||
/* serial numbers */ Collections.singleton("GA-EN-AAEJ"), /* stream IDs */ null);
|
||||
assertTrue(resources.iterator().hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetResourceData() throws ClientProtocolException, IllegalStateException, IOException, ParseException {
|
||||
Map<Type, Double> typesAndCompression = new HashMap<>();
|
||||
public void testGetResourceData() throws ClientProtocolException, IllegalStateException, IOException, ParseException, java.text.ParseException {
|
||||
final Map<Type, Double> typesAndCompression = new HashMap<>();
|
||||
typesAndCompression.put(Type.gps_latlong, 0.0);
|
||||
Iterable<Fix> data = connection.getResourceData(new MillisecondsTimePoint(1384068419000l),
|
||||
new MillisecondsTimePoint(1384091860000l), Collections.singleton("DD-EE-AAGA"), typesAndCompression);
|
||||
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.GERMAN);
|
||||
final TimePoint start = new MillisecondsTimePoint(dateFormat.parse("2025-01-07T07:00:00Z"));
|
||||
final TimePoint end = new MillisecondsTimePoint(dateFormat.parse("2025-01-08T18:00:00Z"));
|
||||
final Iterable<Fix> data = connection.getResourceData(start, end,
|
||||
Collections.singleton("DC-GD-AAED"), typesAndCompression);
|
||||
assertTrue(data.iterator().hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDataAccessWindowForGivenTimeFrame() throws java.text.ParseException, IllegalStateException, ClientProtocolException, IOException, ParseException {
|
||||
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.GERMAN);
|
||||
TimePoint start = new MillisecondsTimePoint(dateFormat.parse("2013-11-07T08:00:00Z"));
|
||||
TimePoint end = new MillisecondsTimePoint(dateFormat.parse("2013-11-09T18:00:00Z"));
|
||||
// URL is https://www.igtimi.com/api/v1/devices/data_access_windows?type=read&start_time=1383811200000&end_time=1383933600000&access_token=3b6cbd0522423bb1ac274ddb9e7e579c4b3be6667622271086c4fdbf30634ba9
|
||||
TimePoint start = new MillisecondsTimePoint(dateFormat.parse("2025-01-07T07:00:00Z"));
|
||||
TimePoint end = new MillisecondsTimePoint(dateFormat.parse("2025-01-08T18:00:00Z"));
|
||||
Iterable<DataAccessWindow> daws = connection.getDataAccessWindows(Permission.read, start, end, /* deviceSerialNumbers; get all devices available for that time */ null);
|
||||
assertFalse(Util.isEmpty(daws));
|
||||
for (DataAccessWindow daw : daws) {
|
||||
@@ -86,15 +77,14 @@ public class BasicIgtimiAdapterTest extends AbstractTestWithIgtimiConnection {
|
||||
@Test
|
||||
public void testResourceDataForGivenTimeFrame() throws java.text.ParseException, IllegalStateException, ClientProtocolException, IOException, ParseException {
|
||||
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.GERMAN);
|
||||
TimePoint start = new MillisecondsTimePoint(dateFormat.parse("2013-11-09T07:00:00Z"));
|
||||
TimePoint end = new MillisecondsTimePoint(dateFormat.parse("2013-11-09T07:10:00Z"));
|
||||
// URL is https://www.igtimi.com/api/v1/devices/data_access_windows?type=read&start_time=1383811200000&end_time=1383933600000&access_token=3b6cbd0522423bb1ac274ddb9e7e579c4b3be6667622271086c4fdbf30634ba9
|
||||
Iterable<DataAccessWindow> daws = connection.getDataAccessWindows(Permission.read, start, end, /* deviceSerialNumbers; get all devices available for that time */ null);
|
||||
Set<String> deviceSerialNumbers = new HashSet<>();
|
||||
for (DataAccessWindow daw : daws) {
|
||||
final TimePoint start = new MillisecondsTimePoint(dateFormat.parse("2025-01-07T07:00:00Z"));
|
||||
final TimePoint end = new MillisecondsTimePoint(dateFormat.parse("2025-01-08T18:00:00Z"));
|
||||
final Iterable<DataAccessWindow> daws = connection.getDataAccessWindows(Permission.read, start, end, /* deviceSerialNumbers; get all devices available for that time */ null);
|
||||
final Set<String> deviceSerialNumbers = new HashSet<>();
|
||||
for (final DataAccessWindow daw : daws) {
|
||||
deviceSerialNumbers.add(daw.getDeviceSerialNumber());
|
||||
}
|
||||
Iterable<Fix> windData = connection.getResourceData(start, end, deviceSerialNumbers, Type.gps_latlong, Type.AWA, Type.AWS, Type.HDG);
|
||||
final Iterable<Fix> windData = connection.getResourceData(start, end, deviceSerialNumbers, Type.gps_latlong, Type.AWA, Type.AWS, Type.HDG);
|
||||
assertFalse(Util.isEmpty(windData));
|
||||
boolean foundWind = false;
|
||||
for (Fix fix : windData) {
|
||||
@@ -106,15 +96,12 @@ public class BasicIgtimiAdapterTest extends AbstractTestWithIgtimiConnection {
|
||||
|
||||
@Test
|
||||
public void testReadLatestData() throws IllegalStateException, ClientProtocolException, IOException, ParseException {
|
||||
Iterable<Fix> fixes = connection.getLatestFixes(Arrays.asList(new String[] { "DD-EE-AAHG", "GA-EN-AAEA", "DD-EE-AAGA" }), Type.SOG );
|
||||
assertEquals(2, Util.size(fixes));
|
||||
Iterable<Fix> fixes = connection.getLatestFixes(Arrays.asList(new String[] { "DC-GD-AAED", "GA-EN-AAEA", "DD-EE-AAGA" }), Type.SOG );
|
||||
assertEquals(1, Util.size(fixes));
|
||||
Iterator<Fix> i = fixes.iterator();
|
||||
Fix fix1 = i.next();
|
||||
assertEquals("DD-EE-AAGA", fix1.getSensor().getDeviceSerialNumber());
|
||||
assertEquals("DC-GD-AAED", fix1.getSensor().getDeviceSerialNumber());
|
||||
assertEquals(Type.SOG, fix1.getType());
|
||||
Fix fix2 = i.next();
|
||||
assertEquals("DD-EE-AAHG", fix2.getSensor().getDeviceSerialNumber());
|
||||
assertEquals(Type.SOG, fix2.getType());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user