Here are the examples of the java api com.iris.population.PlacePopulationCacheManager taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.
91 Examples
19
Source : BaseChangePinRESTHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
abstract clreplaced BasePinRESTHandler extends RESTHandler {
private final ClientFactory clientFactory;
private final AuthorizationGrantDAO authGrantDao;
private final PlatformMessageBus bus;
private final boolean checkPrincipal;
protected final PersonDAO personDao;
protected final PlacePopulationCacheManager populationCacheMgr;
// KEEP - NEEDED BY ALL PIN HANDLERS
protected abstract String extractPin(ClientMessage msg);
protected abstract String extractPlaceId(ClientMessage msg, Person person);
protected abstract MessageBody buildResponseBody(boolean success);
protected abstract MessageBody handlePinOperation(Person person, String pin, String place, List<AuthorizationGrant> grants, ClientMessage clientMessage) throws PinNotUniqueAtPlaceException;
BasePinRESTHandler(ClientFactory clientFactory, PersonDAO personDao, AuthorizationGrantDAO authGrantDao, PlatformMessageBus bus, PlacePopulationCacheManager populationCacheMgr, HttpSender httpSender, RequestAuthorizer auth, RESTHandlerConfig restHandlerConfig, boolean checkPrincipal) {
super(auth, httpSender, restHandlerConfig);
this.clientFactory = clientFactory;
this.personDao = personDao;
this.authGrantDao = authGrantDao;
this.bus = bus;
this.checkPrincipal = checkPrincipal;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public void replacedertValidRequest(FullHttpRequest req, ChannelHandlerContext ctx) {
String json = req.content().toString(CharsetUtil.UTF_8);
ClientMessage clientMessage = JSON.fromJson(json, ClientMessage.clreplaced);
String destination = clientMessage.getDestination();
// FIXME really annoying that we have to load person twice, but would require a pretty major API shift in RESTHandler to fix this
Person person = loadPerson(destination);
PinErrors.replacedertPersonFound(person);
String pin = extractPin(clientMessage);
String place = extractPlaceId(clientMessage, person);
// Validate the request
Errors.replacedertRequiredParam(pin, PersonCapability.VerifyPinRequest.ATTR_PIN);
Errors.replacedertRequiredParam(place, PersonCapability.VerifyPinRequest.ATTR_PLACE);
Errors.replacedertValidRequest(pin.length() == 4 && StringUtils.isNumeric(pin), "pin must be 4 numerical digits");
Client client = clientFactory.get(ctx.channel());
/* Validate the creds and auth */
UUID placeID = UUID.fromString(place);
Address dst = Address.fromString(destination);
List<AuthorizationGrant> grants = authGrantDao.findForEnreplacedy(person.getId());
if (checkPrincipal) {
AuthorizationContext authCtx = client.getAuthorizationContext();
if (permissionsEmpty(authCtx.getInstancePermissions(placeID)) && permissionsEmpty(authCtx.getNonInstancePermissions(placeID))) {
throw new UnauthorizedRequestException(dst, "Unauthorized");
}
UUID loggedInPerson = client.getPrincipalId();
if (!loggedInPerson.equals(person.getId()) && person.getHasLogin()) {
throw new UnauthorizedRequestException(dst, "Unauthorized request, requester must be logged in as the person that the pin is being verified for");
}
}
if (!grants.stream().anyMatch((a) -> {
return a.getPlaceId().equals(placeID);
})) {
throw new UnauthorizedRequestException(dst, "Unauthorized");
}
}
@Override
protected MessageBody doHandle(ClientMessage request) throws Exception {
Person person = loadPerson(request.getDestination());
String pin = extractPin(request);
String place = extractPlaceId(request, person);
List<AuthorizationGrant> grants = authGrantDao.findForEnreplacedy(person.getId());
try {
return handlePinOperation(person, pin, place, grants, request);
} catch (PinNotUniqueAtPlaceException e) {
throw new ErrorEventException(PinErrors.PIN_NOT_UNIQUE_AT_PLACE_CODE, PinErrors.PIN_NOT_UNIQUE_AT_PLACE_MSG);
}
}
private Person loadPerson(String destination) {
Address addr = Address.fromString(destination);
if (addr == null) {
return null;
}
return personDao.findById((UUID) addr.getId());
}
private boolean permissionsEmpty(Collection<? extends Permission> permissions) {
return permissions == null || permissions.isEmpty();
}
protected void broadcastValueChange(Person person, String placeId, List<AuthorizationGrant> grants, boolean hadPin, Set<String> previousPlaces) {
Map<String, Object> attrs = new HashMap<>();
if (person.hasPinAtPlace(placeId) && !hadPin) {
attrs.put(PersonCapability.ATTR_HASPIN, true);
}
if (!Objects.equals(person.getPlacesWithPin(), previousPlaces)) {
attrs.put(PersonCapability.ATTR_PLACESWITHPIN, person.getPlacesWithPin());
}
if (attrs.isEmpty()) {
return;
}
grants.forEach((g) -> {
PlatformMessage broadcast = PlatformMessage.buildBroadcast(MessageBody.buildMessage(Capability.EVENT_VALUE_CHANGE, attrs), Address.fromString(person.getAddress())).withPlaceId(g.getPlaceId()).withPopulation(populationCacheMgr.getPopulationByPlaceId(g.getPlaceId())).create();
bus.send(broadcast);
});
}
// KEEP
protected void notify(Person person, String placeId) {
String population = populationCacheMgr.getPopulationByPlaceId(placeId);
PlatformMessage broadcast = PlatformMessage.buildBroadcast(PinChangedEventEvent.instance(), Address.fromString(person.getAddress())).withPlaceId(placeId).withPopulation(population).create();
bus.send(broadcast);
PlatformMessage msg = Notifications.builder().withSource(Address.platformService(PlatformConstants.SERVICE_PEOPLE)).withPersonId(person.getId()).withPlaceId(UUID.fromString(placeId)).withPopulation(population).withPriority(NotificationCapability.NotifyRequest.PRIORITY_LOW).withMsgKey(Notifications.PinChanged.KEY).create();
bus.send(msg);
}
}
19
Source : PersonHandlerHelper.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
public void sendValueChangeEventForPlace(PlatformMessageBus platformBus, PlacePopulationCacheManager populationCacheMgr, Address sourceAddress, Map<String, Object> changes, String placeId) {
MessageBody body = MessageBody.buildMessage(Capability.EVENT_VALUE_CHANGE, changes);
PlatformMessage msg = PlatformMessage.buildBroadcast(body, sourceAddress).withPlaceId(placeId).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeId)).create();
platformBus.send(msg);
}
19
Source : HubConnectionSessionListener.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
/**
*/
public clreplaced HubConnectionSessionListener extends HubSessionAdapter {
// just need this for the id, kind of annoying
private final Parreplacedioner parreplacedioner;
private final PlatformMessageBus platformBus;
private final PlaceDAO placeDao;
private final HubRegistrationRegistry hubRegistrationRegistry;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public HubConnectionSessionListener(Parreplacedioner parreplacedioner, PlatformMessageBus platformBus, PlaceDAO placeDao, HubRegistrationRegistry hubRegistrationRegistry, PlacePopulationCacheManager populationCacheMgr) {
this.parreplacedioner = parreplacedioner;
this.platformBus = platformBus;
this.placeDao = placeDao;
this.hubRegistrationRegistry = hubRegistrationRegistry;
this.populationCacheMgr = populationCacheMgr;
}
/* (non-Javadoc)
* @see com.iris.hubcom.server.session.listener.HubSessionAdapter#onConnected(com.iris.hubcom.server.session.HubSession)
*/
@Override
public void onConnected(HubSession session) {
super.onConnected(session);
broadcastState(session, HubConnectionCapability.STATE_HANDSHAKE);
}
/* (non-Javadoc)
* @see com.iris.hubcom.server.session.listener.HubSessionAdapter#onAuthorized(com.iris.hubcom.server.session.HubSession)
*/
@Override
public void onAuthorized(HubSession session) {
super.onAuthorized(session);
broadcastState(session, HubConnectionCapability.STATE_ONLINE);
broadcast(session, HubCapability.HubConnectedEvent.instance());
Channel channel = session.getChannel();
SocketAddress addr = channel != null ? channel.remoteAddress() : null;
if (addr == null || !(addr instanceof InetSocketAddress)) {
return;
}
Place place = placeDao.findById(UUID.fromString(session.getActivePlace()));
String timezone = (place != null && place.getTzId() != null) ? place.getTzId() : "";
InetSocketAddress inet = (InetSocketAddress) addr;
MessageBody body = MessageBody.buildMessage(Capability.CMD_SET_ATTRIBUTES, ImmutableMap.of(HubCapability.ATTR_TZ, timezone, HubNetworkCapability.ATTR_EXTERNALIP, inet.getAddress().getHostAddress()));
PlatformMessage msg = PlatformMessage.buildRequest(body, Address.platformService(PlatformConstants.SERVICE_HUB), Address.hubService(session.getHubId(), "hub")).create();
byte[] payload = JSON.createSerializer(PlatformMessage.clreplaced).serialize(msg);
byte[] message = JSON.createSerializer(HubMessage.clreplaced).serialize(HubMessage.createPlatform(payload));
session.sendMessage(message);
}
/* (non-Javadoc)
* @see com.iris.hubcom.server.session.listener.HubSessionAdapter#onDisconnected(com.iris.hubcom.server.session.HubSession)
*/
@Override
public void onDisconnected(HubSession session) {
super.onDisconnected(session);
// note the state change isn't handled here, that's up to the HubService on platform-services
// to ensure this isn't incorrect as a hub bounces between bridges
hubRegistrationRegistry.offline(session.getHubId());
broadcast(session, HubCapability.HubDisconnectedEvent.instance());
}
private void broadcastState(Session session, String state) {
Map<String, Object> attributes = ImmutableMap.<String, Object>of(HubConnectionCapability.ATTR_STATE, state, HubConnectionCapability.ATTR_LASTCHANGE, new Date());
broadcast(session, MessageBody.buildMessage(Capability.EVENT_VALUE_CHANGE, attributes));
}
private void broadcast(Session session, MessageBody body) {
Address address = Address.hubService(session.getClientToken().getRepresentation(), HubCapability.NAMESPACE);
PlatformMessage msg = PlatformMessage.buildBroadcast(body, address).withPlaceId(session.getActivePlace()).withPopulation(populationCacheMgr.getPopulationByPlaceId(session.getActivePlace())).withActor(Address.clientAddress("hub-bridge", String.valueOf(parreplacedioner.getMemberId()))).create();
platformBus.send(msg);
}
}
18
Source : TagHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced TagHandler extends BaseClientRequestHandler {
private static final Logger tagLog = getLogger("tag");
public static final String KEY_SERVICE_LEVEL = "service.level";
private final IrisNettyMessageUtil messageUtil;
private final replacedyticsMessageBus tagBus;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public TagHandler(IrisNettyMessageUtil messageUtil, replacedyticsMessageBus tagBus, PlacePopulationCacheManager populationCacheMgr) {
super(directExecutor());
this.messageUtil = messageUtil;
this.tagBus = tagBus;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public String getRequestType() {
return TagRequest.NAME;
}
@Override
protected MessageBody doHandle(ClientMessage request, Session session) {
MessageBody requestBody = request.getPayload();
String tagName = TagRequest.getName(requestBody);
Map<String, String> tagContext = TagRequest.getContext(requestBody);
tagLog.info("Tag {} : {}", tagName, tagContext);
// These two will be null for UI tags before the user logs in
String placeId = session.getActivePlace();
UUID personId = session.getClient().getPrincipalId();
String serviceLevel = tagContext.get(KEY_SERVICE_LEVEL);
if (isBlank(serviceLevel)) {
serviceLevel = null;
}
MessageBody eventBody = TaggedEvent.builder().withName(tagName).withPlaceId(placeId).withPersonId(personId == null ? null : personId.toString()).withSource(upperCase(session.getClientType())).withVersion(session.getClientVersion()).withServiceLevel(serviceLevel).build();
Address clientAddress = Address.fromString(messageUtil.buildId(session.getClientToken().getRepresentation()));
Address personAddress = personId == null ? null : Address.platformService(personId, PersonCapability.NAMESPACE);
tagBus.send(PlatformMessage.buildEvent(eventBody, clientAddress).withPlaceId(placeId).withPopulation(populationCacheMgr.getPopulationByPlaceId(UUID.fromString(placeId))).withActor(personAddress).create());
return TagResponse.instance();
}
@Override
protected Address address() {
return SessionService.ADDRESS;
}
}
18
Source : RecordingEventPublisher.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
// code formerly in VideoRecordingDao, pulled out to break the tight coupling between video recording dao and event
// messaging to allow different recording server styles to control when they issue events but keep the eventing the
// same
@Singleton
public clreplaced RecordingEventPublisher {
private final PlatformMessageBus bus;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public RecordingEventPublisher(PlatformMessageBus bus, PlacePopulationCacheManager populationCacheMgr) {
this.bus = bus;
this.populationCacheMgr = populationCacheMgr;
}
public void sendAdded(VideoMetadata metadata) {
if (metadata != null) {
try {
Address addr = Address.platformService(metadata.getRecordingId(), RecordingCapability.NAMESPACE);
MessageBody body = MessageBody.buildMessage(Capability.EVENT_ADDED, metadata.toMap());
PlatformMessage evt = PlatformMessage.buildBroadcast(body, addr).withActor(VideoUtil.getActorFromPersonId(metadata.getPlaceId(), metadata.getPersonId())).withPlaceId(metadata.getPlaceId()).withPopulation(populationCacheMgr.getPopulationByPlaceId(metadata.getPlaceId())).create();
bus.send(evt);
RECORDING_ADDED_SUCCESS.inc();
} catch (Exception ex) {
RECORDING_ADDED_FAIL.inc();
throw ex;
}
}
}
public void sendValueChange(UUID placeId, UUID recordingId, double duration, long size, Date purgeAt) {
Map<String, Object> attrs = ImmutableMap.of(RecordingCapability.ATTR_DURATION, duration, RecordingCapability.ATTR_SIZE, size, RecordingCapability.ATTR_DELETED, true, RecordingCapability.ATTR_DELETETIME, purgeAt, RecordingCapability.ATTR_COMPLETED, isCompleted(duration));
sendValueChangeEvent(placeId, recordingId, attrs);
}
private boolean isCompleted(double duration) {
return duration > 0.0;
}
public void sendValueChange(UUID placeId, UUID recordingId, double duration, long size) {
Map<String, Object> attrs = ImmutableMap.of(RecordingCapability.ATTR_SIZE, size, RecordingCapability.ATTR_DURATION, duration, RecordingCapability.ATTR_COMPLETED, isCompleted(duration));
sendValueChangeEvent(placeId, recordingId, attrs);
}
private void sendValueChangeEvent(UUID placeId, UUID recordingId, Map<String, Object> attrs) {
try {
Address addr = Address.platformService(recordingId, RecordingCapability.NAMESPACE);
MessageBody body = MessageBody.buildMessage(Capability.EVENT_VALUE_CHANGE, attrs);
PlatformMessage evt = PlatformMessage.buildBroadcast(body, addr).withPlaceId(placeId).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeId)).create();
bus.send(evt);
RECORDING_VC_SUCCESS.inc();
} catch (Exception ex) {
RECORDING_VC_FAIL.inc();
throw ex;
}
}
}
18
Source : VideoRecordingManager.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced VideoRecordingManager {
private final VideoConfig config;
private final VideoDao videoDao;
private final PlatformMessageBus platformBus;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public VideoRecordingManager(VideoConfig config, PlatformMessageBus platformBus, VideoDao videoRecordingDao, PlacePopulationCacheManager populationCacheMgr) {
this.config = config;
this.videoDao = videoRecordingDao;
this.platformBus = platformBus;
this.populationCacheMgr = populationCacheMgr;
}
public VideoMetadata storeMetadata(VideoStorageSession storage, int width, int height, int bandwidth, double framerate, double precapture, boolean stream) throws Exception {
return storeMetadata(storage, width, height, bandwidth, framerate, precapture, stream, VideoCodec.H264_BASELINE_3_1, AudioCodec.NONE);
}
public VideoMetadata storeMetadata(VideoStorageSession storage, int width, int height, int bandwidth, double framerate, double precapture, boolean stream, VideoCodec vc, AudioCodec ac) throws Exception {
try {
VideoMetadata metadata = new VideoMetadata();
metadata.setAccountId(storage.getAccountId());
metadata.setPlaceId(storage.getPlaceId());
metadata.setExpiration(VideoV2Util.createExpirationFromTTL(storage.getRecordingId(), storage.getRecordingTtlInSeconds()));
metadata.setCameraId(storage.getCameraId());
metadata.setRecordingId(storage.getRecordingId());
metadata.setPersonId(storage.getPersonId());
metadata.setLoc(storage.location());
metadata.setName(VideoDao.defaultName(storage.getRecordingId()));
metadata.setWidth(width);
metadata.setHeight(height);
metadata.setFramerate(framerate);
metadata.setPrecapture(precapture);
metadata.setStream(stream);
metadata.setBandwidth(bandwidth);
metadata.setVideoCodec(vc);
metadata.setAudioCodec(ac);
videoDao.insert(metadata);
RECORDING_SESSION_STOREMD_SUCCESS.inc();
return metadata;
} catch (Exception e) {
RECORDING_SESSION_STOREMD_FAIL.inc();
throw e;
}
}
public void storeIFrame(VideoStorageSession storage, double tsInSeconds, long frameByteOffset, long frameByteSize) throws Exception {
try {
UUID recId = storage.getRecordingId();
videoDao.insertIFrame(recId, tsInSeconds, frameByteOffset, frameByteSize, storage.getRecordingTtlInSeconds());
RECORDING_SESSION_STOREIF_SUCCESS.inc();
} catch (Exception e) {
RECORDING_SESSION_STOREIF_FAIL.inc();
throw e;
}
}
/**
* @param storage
* @param duration
* @param size
* @param stream
* @return Optionally the date that the video was purged at if the recording was to be purged at completion time.
* @throws Exception
*/
public Optional<Date> storeDurationAndSize(VideoStorageSession storage, double duration, long size, boolean stream) throws Exception {
try {
RECORDING_DURATION.update((long) (duration * 1000000000), TimeUnit.NANOSECONDS);
UUID plcId = storage.getPlaceId();
UUID recId = storage.getRecordingId();
Date purgeAt = null;
if (stream || size == 0) {
// immediately delete streams and 0 sized recordings on completion
purgeAt = VideoUtil.getPurgeTimestamp(config.getPurgeDelay(), TimeUnit.MILLISECONDS);
int parreplacedion = VideoDao.calculateParreplacedionId(recId, config.getPurgeParreplacedions());
videoDao.completeAndDelete(plcId, recId, duration, size, purgeAt, parreplacedion, storage.getRecordingTtlInSeconds());
} else {
videoDao.complete(plcId, recId, duration, size, storage.getRecordingTtlInSeconds());
}
RECORDING_TOTAL_TIME.inc((long) duration);
RECORDING_TOTAL_BYTES.inc(size);
RECORDING_SESSION_STOREDS_SUCCESS.inc();
return Optional.ofNullable(purgeAt);
} catch (Exception e) {
RECORDING_SESSION_STOREDS_FAIL.inc();
throw e;
}
}
}
18
Source : RuleTemplateRequestor.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced RuleTemplateRequestor {
public static final String NAME_EXECUTOR = "executor.ruletemplaterequest";
private final PlatformBusClient requestor;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public RuleTemplateRequestor(@Named(NAME_EXECUTOR) Executor executor, PlatformMessageBus bus, PlacePopulationCacheManager populationCacheMgr, PairingCustomizationConfig config) {
this.requestor = new PlatformBusClient(bus, executor, config.getRuleTemplateRequestTimeoutMs(), ImmutableSet.of(AddressMatchers.equals(PairingDeviceService.ADDRESS)));
this.populationCacheMgr = populationCacheMgr;
}
public ListenableFuture<List<Map<String, Object>>> listTemplatesForPlace(UUID placeId) {
MessageBody listTemplates = ListRuleTemplatesRequest.builder().withPlaceId(placeId.toString()).build();
PlatformMessage request = PlatformMessage.request(RuleService.ADDRESS).from(PairingDeviceService.ADDRESS).withCorrelationId(IrisUUID.randomUUID().toString()).withPlaceId(placeId).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeId)).withPayload(listTemplates).create();
return Futures.transform(requestor.request(request), (Function<PlatformMessage, List<Map<String, Object>>>) (message) -> ListRuleTemplatesResponse.getRuleTemplates(message.getValue(), ImmutableList.of()), MoreExecutors.directExecutor());
}
}
18
Source : CassandraPairingDeviceDao.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
public clreplaced CreplacedandraPairingDeviceDao extends BaseModelDao<PairingDevice> implements PairingDeviceDao {
private final PreparedStatement listByPlace;
private final PreparedStatement findByPlaceAndProtocolAddress;
private final PreparedStatement upsertIfSequenceIs;
private final PreparedStatement updateIf;
private final PreparedStatement deleteByPlace;
private final PreparedStatement deleteByPlaceAndProtocolAddress;
private final PreparedStatement findSequenceIdByPlace;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public CreplacedandraPairingDeviceDao(DefinitionRegistry registry, Session session, PlacePopulationCacheManager populationCacheMgr) {
super(registry, session);
this.listByPlace = CreplacedandraQueryBuilder.select(PairingDeviceTable.NAME).addColumns(PairingDeviceTable.Column.values()).addWhereColumnEquals(PairingDeviceTable.Column.placeId).prepare(session);
this.findByPlaceAndProtocolAddress = CreplacedandraQueryBuilder.select(PairingDeviceTable.NAME).addColumns(PairingDeviceTable.Column.values()).addWhereColumnEquals(PairingDeviceTable.Column.placeId).addWhereColumnEquals(PairingDeviceTable.Column.protocolAddress).prepare(session);
this.upsertIfSequenceIs = CreplacedandraQueryBuilder.update(PairingDeviceTable.NAME).addColumns(PairingDeviceTable.StaticColumn.IdSequence).addColumns(PairingDeviceTable.Column.sequenceId).addColumns(PairingDeviceTable.Column.attributes).addColumns(PairingDeviceTable.Column.modified).addColumns(PairingDeviceTable.Column.created).addWhereColumnEquals(PairingDeviceTable.Column.placeId).addWhereColumnEquals(PairingDeviceTable.Column.protocolAddress).ifClause(String.format("%s = ?", PairingDeviceTable.StaticColumn.IdSequence.name())).prepare(session);
this.updateIf = CreplacedandraQueryBuilder.update(PairingDeviceTable.NAME).addColumns(PairingDeviceTable.Column.attributes).addColumns(PairingDeviceTable.Column.modified).addWhereColumnEquals(PairingDeviceTable.Column.placeId).addWhereColumnEquals(PairingDeviceTable.Column.protocolAddress).ifExists().prepare(session);
this.deleteByPlace = CreplacedandraQueryBuilder.delete(PairingDeviceTable.NAME).addWhereColumnEquals(PairingDeviceTable.Column.placeId).prepare(session);
this.deleteByPlaceAndProtocolAddress = CreplacedandraQueryBuilder.delete(PairingDeviceTable.NAME).addWhereColumnEquals(PairingDeviceTable.Column.placeId).addWhereColumnEquals(PairingDeviceTable.Column.protocolAddress).prepare(session);
this.findSequenceIdByPlace = CreplacedandraQueryBuilder.select(PairingDeviceTable.NAME).addColumn(PairingDeviceTable.StaticColumn.IdSequence).addWhereColumnEquals(PairingDeviceTable.Column.placeId).limit(1).prepare(session);
this.populationCacheMgr = populationCacheMgr;
}
@Override
public List<PairingDevice> listByPlace(UUID placeId) {
try (Context ctx = Metrics.listByPlaceTimer.time()) {
return list(listByPlace.bind(placeId));
}
}
@Override
@Nullable
public PairingDevice findById(UUID placeId, int contextId) {
return listByPlace(placeId).stream().filter((m) -> contextId == m.getContextId()).findAny().orElse(null);
}
@Override
@Nullable
public PairingDevice findByProtocolAddress(UUID placeId, Address protocolAddress) {
try (Context ctx = Metrics.findByProtocolAddressTimer.time()) {
return find(findByPlaceAndProtocolAddress.bind(placeId, protocolAddress.getRepresentation())).orElse(null);
}
}
@Override
public PairingDevice save(PairingDevice enreplacedy) throws IllegalArgumentException {
Preconditions.checkArgument(enreplacedy.getPlaceId() != null, "Must specify a place id");
Preconditions.checkArgument(enreplacedy.getProtocolAddress() != null, "Must specify a protocol address");
enreplacedy.setPopulation(populationCacheMgr.getPopulationByPlaceId(enreplacedy.getPlaceId()));
if (!enreplacedy.isPersisted()) {
return insert(enreplacedy);
} else {
return update(enreplacedy);
}
}
private PairingDevice insert(PairingDevice enreplacedy) {
try (Context ctx = Metrics.insertTimer.time()) {
PairingDevice copy = enreplacedy.copy();
copy.setCreated(new Date());
copy.setModified(copy.getCreated());
OptionalInt currentId = OptionalInt.of(getCurrentId(enreplacedy.getPlaceId()));
// FIXME add a max retry?
while (currentId.isPresent()) {
copy.setId(copy.getPlaceId(), currentId.getAsInt());
currentId = tryInsert(currentId.getAsInt(), copy);
}
return copy;
}
}
// package scope for testing
OptionalInt tryInsert(int currentId, PairingDevice copy) {
BoundStatement bs = upsertIfSequenceIs.bind(// update idSequence to next value
currentId + 1, // set this row's id to the current id
currentId, encode(copy.getAttributes()), copy.getModified(), copy.getCreated(), copy.getPlaceId(), copy.getProtocolAddress().getRepresentation(), currentId > 0 ? currentId : null);
ResultSet rs = session().execute(bs);
if (!rs.wasApplied()) {
// replacedume failures are do to idSequence having changed, get the new value to allow retries
return OptionalInt.of(rs.one().getInt(PairingDeviceTable.StaticColumn.IdSequence.name()));
} else {
return OptionalInt.empty();
}
}
private int getCurrentId(UUID placeId) {
ResultSet rs = session().execute(findSequenceIdByPlace.bind(placeId));
return Optional.ofNullable(rs.one()).map((row) -> row.getInt(PairingDeviceTable.StaticColumn.IdSequence.name())).orElse(0);
}
private PairingDevice update(PairingDevice enreplacedy) {
Preconditions.checkState(enreplacedy.getId() != null, "Attempting to update a pairing device model with a create date but no secondary id");
try (Context ctx = Metrics.updateTimer.time()) {
Date modified = new Date();
BoundStatement bs = updateIf.bind(encode(enreplacedy.getAttributes()), modified, enreplacedy.getPlaceId(), enreplacedy.getProtocolAddress().getRepresentation());
if (!session().execute(bs).wasApplied()) {
throw new NotFoundException(enreplacedy.getAddress());
}
PairingDevice copy = enreplacedy.copy();
copy.setModified(modified);
return copy;
}
}
@Override
public void deleteByPlace(UUID placeId) {
try (Context ctx = Metrics.deleteByPlaceTimer.time()) {
session().execute(deleteByPlace.bind(placeId));
}
}
@Override
public void delete(PairingDevice model) {
try (Context ctx = Metrics.deleteTimer.time()) {
session().execute(deleteByPlaceAndProtocolAddress.bind(model.getPlaceId(), model.getProtocolAddress().getRepresentation()));
}
}
@Override
protected PairingDevice toModel(Row row) {
// strange side-effect of using a static column is that there is a special row with a null protocoladdress that holds static value when all other rows have been deleted
if (row.isNull(PairingDeviceTable.Column.protocolAddress.name())) {
return null;
}
Map<String, Object> attributes = decode(row.getMap(PairingDeviceTable.Column.attributes.name(), String.clreplaced, String.clreplaced));
// construct with attributes so those fields aren't marked as dirty
// the existence of the mock attribute indicates this is a mock or not
PairingDevice enreplacedy = attributes.containsKey(PairingDeviceMockCapability.ATTR_TARGETPRODUCTADDRESS) ? new PairingDeviceMock(attributes) : new PairingDevice(attributes);
enreplacedy.setId(row.getUUID(PairingDeviceTable.Column.placeId.name()), row.getInt(PairingDeviceTable.Column.sequenceId.name()));
enreplacedy.setProtocolAddress((DeviceProtocolAddress) Address.fromString(row.getString(PairingDeviceTable.Column.protocolAddress.name())));
enreplacedy.setModified(row.getTimestamp(PairingDeviceTable.Column.modified.name()));
enreplacedy.setCreated(row.getTimestamp(PairingDeviceTable.Column.created.name()));
enreplacedy.setPopulation(populationCacheMgr.getPopulationByPlaceId(enreplacedy.getPlaceId()));
return enreplacedy;
}
}
18
Source : SceneCatalogLoader.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced SceneCatalogLoader {
private final SceneCatalogManager manager;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public SceneCatalogLoader(SceneCatalogManager manager, PlacePopulationCacheManager populationCacheMgr) {
this.manager = manager;
this.populationCacheMgr = populationCacheMgr;
}
public SceneCatalog getCatalogForPlace(UUID placeId) {
String population = populationCacheMgr.getPopulationByPlaceId(placeId);
return getCatalogForPopulation(population);
}
private SceneCatalog getCatalogForPopulation(String population) {
return manager.getCatalog(population);
}
}
18
Source : RuleCatalogLoader.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
/**
*/
@Singleton
public clreplaced RuleCatalogLoader {
private final RuleCatalogManager manager;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public RuleCatalogLoader(RuleCatalogManager manager, PlacePopulationCacheManager populationCacheMgr) {
this.manager = manager;
this.populationCacheMgr = populationCacheMgr;
}
public RuleCatalog getCatalogForPlace(UUID placeId) {
String population = populationCacheMgr.getPopulationByPlaceId(placeId);
return getCatalogForPopulation(population);
}
private RuleCatalog getCatalogForPopulation(String population) {
return manager.getCatalog(population);
}
}
18
Source : SendInvitationHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced SendInvitationHandler implements ContextualRequestMessageHandler<Place> {
private final PersonDAO personDao;
private final AccountDAO accountDao;
private final InvitationDAO invitationDao;
private final AuthorizationGrantDAO authGrantDao;
private final PlatformMessageBus bus;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public SendInvitationHandler(PersonDAO personDao, AccountDAO accountDao, InvitationDAO invitationDao, AuthorizationGrantDAO authGrantDao, PlatformMessageBus bus, PlacePopulationCacheManager populationCacheMgr) {
this.personDao = personDao;
this.accountDao = accountDao;
this.invitationDao = invitationDao;
this.authGrantDao = authGrantDao;
this.bus = bus;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public String getMessageType() {
return PlaceCapability.SendInvitationRequest.NAME;
}
@Override
public MessageBody handleRequest(Place context, PlatformMessage msg) {
Invitation inv = new Invitation(PlaceCapability.SendInvitationRequest.getInvitation(msg.getValue()));
validate(inv);
Person invitor = InvitationHandlerHelper.getActorFromMessage(msg, personDao);
Person accountOwner = invitor;
if (!Objects.equals(invitor.getAccountId(), context.getAccount())) {
accountOwner = getOwner(context.getAccount());
}
Person invitee = findInvitee(inv.getInviteeEmail());
inv.setPlaceId(context.getId().toString());
inv.setPlaceName(context.getName());
inv.setStreetAddress1(context.getStreetAddress1());
inv.setStreetAddress2(context.getStreetAddress2());
inv.setCity(context.getCity());
inv.setStateProv(context.getStateProv());
inv.setZipCode(context.getZipCode());
if (invitee != null) {
inv.setInviteeId(invitee.getId().toString());
}
inv.setInvitorId(invitor.getId().toString());
inv.setInvitorFirstName(invitor.getFirstName());
inv.setInvitorLastName(invitor.getLastName());
inv.setPlaceOwnerId(accountOwner.getId().toString());
inv.setPlaceOwnerFirstName(accountOwner.getFirstName());
inv.setPlaceOwnerLastName(accountOwner.getLastName());
invitationDao.insert(inv);
emitInvitationPending(context, invitee);
sendInvite(inv);
if (!InvitationHandlerHelper.isInviterSameAsOwner(inv)) {
// inviter is not the account owner, so send notification to the account owner
sendNotificationToAccountOwner(invitor, inv);
}
return PlaceCapability.SendInvitationResponse.instance();
}
private void sendNotificationToAccountOwner(Person invitor, Invitation inv) {
InvitationHandlerHelper.sendEmailNotification(bus, inv.getPlaceOwnerId(), inv.getPlaceId(), populationCacheMgr.getPopulationByPlaceId(inv.getPlaceId()), Notifications.PersonInvitedToJoinNotifyOwner.KEY, ImmutableMap.<String, String>of(Notifications.PersonInvitedToJoinNotifyOwner.PARAM_INVITEE_FIRSTNAME, Notifications.ensureNotNull(inv.getInviteeFirstName()), Notifications.PersonInvitedToJoinNotifyOwner.PARAM_INVITEE_LASTNAME, Notifications.ensureNotNull(inv.getInviteeLastName()), Notifications.PersonInvitedToJoinNotifyOwner.PARAM_INVITER_FIRSTNAME, Notifications.ensureNotNull(invitor.getFirstName()), Notifications.PersonInvitedToJoinNotifyOwner.PARAM_INVITER_LASTNAME, Notifications.ensureNotNull(invitor.getLastName())));
}
private void emitInvitationPending(Place context, Person invitee) {
if (invitee == null) {
return;
}
// send event to every place because we don't know which one the user is logged into if any
List<AuthorizationGrant> grants = authGrantDao.findForEnreplacedy(invitee.getId());
grants.forEach((g) -> {
emitInvitationPending(context, invitee, g.getPlaceId());
});
}
private void emitInvitationPending(Place context, Person invitee, UUID placeId) {
PlatformMessage msg = PlatformMessage.buildBroadcast(PersonCapability.InvitationPendingEvent.instance(), Address.fromString(context.getAddress())).withPlaceId(placeId).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeId)).create();
bus.send(msg);
}
private void sendInvite(Invitation invitation) {
Map<String, String> args = new HashMap<>();
args.put(Notifications.PersonInvitedToJoin.PARAM_CODE, invitation.getCode());
args.put(Notifications.PersonInvitedToJoin.PARAM_INVITATIONTEXT, invitation.getInvitationText());
args.put(Notifications.PersonInvitedToJoin.PARAM_INVITEEFIRSTNAME, invitation.getInviteeFirstName());
args.put(Notifications.PersonInvitedToJoin.PARAM_INVITEELASTNAME, invitation.getInviteeLastName());
args.put(Notifications.PersonInvitedToJoin.PARAM_INVITORFIRSTNAME, invitation.getInvitorFirstName());
args.put(Notifications.PersonInvitedToJoin.PARAM_INVITORLASTNAME, invitation.getInvitorLastName());
args.put(Notifications.PersonInvitedToJoin.PARAM_PERSONALIZEDGREETING, invitation.getPersonalizedGreeting() == null ? "" : invitation.getPersonalizedGreeting());
InvitationHandlerHelper.sendEmailNotificationToInvitee(bus, invitation, populationCacheMgr.getPopulationByPlaceId(invitation.getPlaceId()), Notifications.PersonInvitedToJoin.KEY, args);
}
private Person getOwner(UUID accountID) {
Account account = accountDao.findById(accountID);
return personDao.findById(account.getOwner());
}
private Person findInvitee(String email) {
return personDao.findByEmail(email);
}
private void validate(Invitation inv) {
if (inv == null) {
throw new ErrorEventException(Errors.CODE_MISSING_PARAM, "invitation is required");
}
Errors.replacedertValidRequest(!StringUtils.isBlank(inv.getInviteeEmail()), "inviteeEmail is required");
Errors.replacedertValidRequest(!StringUtils.isBlank(inv.getInviteeFirstName()), "inviteeFirstName is required");
Errors.replacedertValidRequest(!StringUtils.isBlank(inv.getInviteeLastName()), "inviteeLastName is required");
}
}
18
Source : CancelInvitationHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced CancelInvitationHandler implements ContextualRequestMessageHandler<Place> {
private final InvitationDAO invitationDao;
private final PlatformMessageBus bus;
private final PersonDAO personDao;
private final AuthorizationGrantDAO authGrantDao;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public CancelInvitationHandler(InvitationDAO invitationDao, PersonDAO personDao, AuthorizationGrantDAO authGrantDao, PlatformMessageBus bus, PlacePopulationCacheManager populationCacheMgr) {
this.invitationDao = invitationDao;
this.personDao = personDao;
this.authGrantDao = authGrantDao;
this.bus = bus;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public String getMessageType() {
return PlaceCapability.CancelInvitationRequest.NAME;
}
@Override
public MessageBody handleRequest(Place context, PlatformMessage msg) {
MessageBody body = msg.getValue();
validate(body);
String code = PlaceCapability.CancelInvitationRequest.getCode(body);
Invitation invitation = invitationDao.find(code);
if (invitation != null) {
if (invitation.getAccepted() != null || invitation.getRejected() != null) {
return PlaceCapability.CancelInvitationResponse.instance();
}
if (!Objects.equals(context.getId().toString(), invitation.getPlaceId())) {
throw new ErrorEventException(Errors.CODE_INVALID_REQUEST, "invitation " + code + " not for place " + context.getId());
}
invitationDao.cancel(invitation);
emitInvitationCancelled(context, invitation);
Person invitationCancelledByPerson = InvitationHandlerHelper.getActorFromMessage(msg, personDao);
if (invitationCancelledByPerson != null) {
sendNotifications(invitation, invitationCancelledByPerson);
}
}
return PlaceCapability.CancelInvitationResponse.instance();
}
private void emitInvitationCancelled(Place context, Invitation invitation) {
if (invitation.getInviteeId() == null) {
return;
}
// Send event to every place because we don't know which one the user is logged into, if any
List<AuthorizationGrant> grants = authGrantDao.findForEnreplacedy(UUID.fromString(invitation.getInviteeId()));
grants.forEach(g -> emitInvitationCancelled(context, g.getPlaceId()));
}
private void emitInvitationCancelled(Place context, UUID placeId) {
PlatformMessage msg = PlatformMessage.buildBroadcast(PersonCapability.InvitationCancelledEvent.instance(), Address.fromString(context.getAddress())).withPlaceId(placeId).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeId)).create();
bus.send(msg);
}
private void sendNotifications(Invitation invite, Person invitationCancelledByPerson) {
String population = populationCacheMgr.getPopulationByPlaceId(invite.getPlaceId());
// Send notification to inviter
InvitationHandlerHelper.sendEmailNotification(bus, invite.getInvitorId(), invite.getPlaceId(), population, Notifications.PersonInvitationCancelled.KEY, ImmutableMap.<String, String>of(Notifications.PersonInvitationCancelled.PARAM_INVITEE_FIRSTNAME, invite.getInviteeFirstName(), Notifications.PersonInvitationCancelled.PARAM_INVITEE_LASTNAME, invite.getInviteeLastName(), Notifications.PersonInvitationCancelled.PARAM_PERSON_CANCELLED_FIRSTNAME, invitationCancelledByPerson.getFirstName(), Notifications.PersonInvitationCancelled.PARAM_PERSON_CANCELLED_LASTNAME, invitationCancelledByPerson.getLastName()));
// If owner is not the same as inviter, send notification to account owner
if (!InvitationHandlerHelper.isInviterSameAsOwner(invite)) {
InvitationHandlerHelper.sendEmailNotification(bus, invite.getPlaceOwnerId(), invite.getPlaceId(), population, Notifications.PersonInvitationCancelled.KEY, ImmutableMap.<String, String>of(Notifications.PersonInvitationCancelled.PARAM_INVITEE_FIRSTNAME, invite.getInviteeFirstName(), Notifications.PersonInvitationCancelled.PARAM_INVITEE_LASTNAME, invite.getInviteeLastName(), Notifications.PersonInvitationCancelled.PARAM_PERSON_CANCELLED_FIRSTNAME, invitationCancelledByPerson.getFirstName(), Notifications.PersonInvitationCancelled.PARAM_PERSON_CANCELLED_LASTNAME, invitationCancelledByPerson.getLastName()));
}
// Send notification to the invitee
InvitationHandlerHelper.sendEmailNotificationToInvitee(bus, invite, population, Notifications.PersonInvitationCancelledNotifyInvitee.KEY, ImmutableMap.<String, String>of(Notifications.PersonInvitationCancelledNotifyInvitee.PARAM_INVITEE_FIRSTNAME, invite.getInviteeFirstName(), Notifications.PersonInvitationCancelledNotifyInvitee.PARAM_INVITEE_LASTNAME, invite.getInviteeLastName(), Notifications.PersonInvitationCancelledNotifyInvitee.PARAM_INVITER_FIRSTNAME, invite.getInvitorFirstName(), Notifications.PersonInvitationCancelledNotifyInvitee.PARAM_INVITER_LASTNAME, invite.getInvitorLastName()));
}
private void validate(MessageBody body) {
Errors.replacedertRequiredParam(PlaceCapability.CancelInvitationRequest.getCode(body), "code");
}
}
18
Source : RejectInvitationHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced RejectInvitationHandler implements ContextualRequestMessageHandler<Person> {
private final InvitationDAO invitationDao;
private final PlatformMessageBus bus;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public RejectInvitationHandler(InvitationDAO invitationDao, PlatformMessageBus bus, PlacePopulationCacheManager populationCacheMgr) {
this.invitationDao = invitationDao;
this.bus = bus;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public String getMessageType() {
return PersonCapability.RejectInvitationRequest.NAME;
}
@Override
public MessageBody handleRequest(Person context, PlatformMessage msg) {
MessageBody body = msg.getValue();
validate(body);
String code = PersonCapability.RejectInvitationRequest.getCode(body);
String email = PersonCapability.RejectInvitationRequest.getInviteeEmail(body);
Invitation invite = invitationDao.find(code);
if (invite == null) {
throw new ErrorEventException(Errors.CODE_NOT_FOUND, "invitation " + code + " not found");
}
if (!Objects.equals(email, invite.getInviteeEmail())) {
throw new ErrorEventException(Errors.CODE_NOT_FOUND, "invitation " + code + " for " + email + " not found");
}
if (invite.getInviteeId() != null && !Objects.equals(invite.getInviteeId(), context.getId().toString())) {
throw new ErrorEventException(Errors.CODE_INVALID_REQUEST, "invitation " + code + " not for person " + context.getId());
}
if (invite.getAccepted() != null || invite.getRejected() != null) {
throw new ErrorEventException(Errors.CODE_INVALID_REQUEST, "invitation " + code + " has already been accepted or rejected.");
}
invitationDao.reject(code, PersonCapability.RejectInvitationRequest.getReason(body));
// send notifications and events
sendNotifications(invite);
emitEvent(context, invite);
return PersonCapability.RejectInvitationResponse.instance();
}
private void emitEvent(Person context, Invitation invite) {
UUID placeId = UUID.fromString(invite.getPlaceId());
PlatformMessage msg = PlatformMessage.buildBroadcast(PersonCapability.InvitationRejectedEvent.builder().withInvitation(invite.toMap()).build(), Address.fromString(context.getAddress())).withPlaceId(placeId).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeId)).withActor(Address.fromString(context.getAddress())).create();
bus.send(msg);
}
private void sendNotifications(Invitation invite) {
String population = populationCacheMgr.getPopulationByPlaceId(invite.getPlaceId());
// Send notification to inviter
InvitationHandlerHelper.sendEmailNotification(bus, invite.getInvitorId(), invite.getPlaceId(), population, Notifications.PersonDeclinedToJoinNotifyInviter.KEY, ImmutableMap.<String, String>of(Notifications.PersonDeclinedToJoinNotifyInviter.PARAM_INVITEE_FIRSTNAME, invite.getInviteeFirstName(), Notifications.PersonDeclinedToJoinNotifyInviter.PARAM_INVITEE_LASTNAME, invite.getInviteeLastName()));
// If owner is not the same as inviter, send notification to account owner
if (!InvitationHandlerHelper.isInviterSameAsOwner(invite)) {
InvitationHandlerHelper.sendEmailNotification(bus, invite.getPlaceOwnerId(), invite.getPlaceId(), population, Notifications.PersonDeclinedToJoinNotifyOwner.KEY, ImmutableMap.<String, String>of(Notifications.PersonDeclinedToJoinNotifyOwner.PARAM_INVITEE_FIRSTNAME, invite.getInviteeFirstName(), Notifications.PersonDeclinedToJoinNotifyOwner.PARAM_INVITEE_LASTNAME, invite.getInviteeLastName()));
}
}
private void validate(MessageBody body) {
Errors.replacedertRequiredParam(PersonCapability.RejectInvitationRequest.getCode(body), "code");
Errors.replacedertRequiredParam(PersonCapability.RejectInvitationRequest.getInviteeEmail(body), "inviteeEmail");
}
}
18
Source : AccountActivateHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced AccountActivateHandler implements ContextualRequestMessageHandler<Account> {
public final static String ERROR_INVALID_STATE = "account.state.invalid";
private final static String ERROR_MSG_OWNER_NAME_MISSING = "Must specify account owner's name";
private final static String ERROR_MSG_OWNER_MISSING = "Must have an account owner";
private final AccountDAO accountDao;
private final PlatformMessageBus platformBus;
private final PersonDAO personDao;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public AccountActivateHandler(AccountDAO accountDao, PersonDAO personDao, PlatformMessageBus platformBus, PlacePopulationCacheManager populationCacheMgr) {
this.accountDao = accountDao;
this.personDao = personDao;
this.platformBus = platformBus;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public String getMessageType() {
return AccountCapability.ActivateRequest.NAME;
}
@Override
public MessageBody handleRequest(Account context, PlatformMessage msg) {
String curState = context.getState();
if (Account.AccountState.COMPLETE.equalsIgnoreCase(curState)) {
return AccountCapability.ActivateResponse.instance();
}
validateAccount(context);
context.setState(Account.AccountState.COMPLETE);
accountDao.save(context);
if (curState == null || Account.AccountState.SIGN_UP_1.equalsIgnoreCase(curState)) {
AccountStateTransitionUtils.sendAccountCreatedNotification(context.getOwner(), platformBus);
}
sendValueChange(context);
return AccountCapability.ActivateResponse.instance();
}
/**
* Send a value for the account state change to every place replacedociated with the account
* @param context
*/
private void sendValueChange(Account context) {
Set<UUID> placeIds = context.getPlaceIDs();
if (!CollectionUtils.isEmpty(placeIds)) {
MessageBody msgBody = MessageBody.buildMessage(Capability.EVENT_VALUE_CHANGE, ImmutableMap.<String, Object>of(AccountCapability.ATTR_STATE, context.getState()));
Address source = Address.fromString(context.getAddress());
placeIds.forEach(placeId -> {
PlatformMessage message = PlatformMessage.buildBroadcast(msgBody, source).withPlaceId(placeId).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeId)).create();
platformBus.send(message);
});
}
}
/**
* Make sure the account has sufficient data to be marked as COMPLETE
* @param context
*/
private void validateAccount(Account context) {
// for now, just make sure owner has name
UUID ownerId = context.getOwner();
if (ownerId == null) {
throw new ErrorEventException(Errors.fromCode(ERROR_INVALID_STATE, ERROR_MSG_OWNER_MISSING));
} else {
Person owner = personDao.findById(ownerId);
if (owner == null) {
throw new ErrorEventException(Errors.fromCode(ERROR_INVALID_STATE, ERROR_MSG_OWNER_MISSING));
} else {
if (StringUtils.isBlank(owner.getFirstName()) || StringUtils.isBlank(owner.getLastName())) {
throw new ErrorEventException(Errors.fromCode(ERROR_INVALID_STATE, ERROR_MSG_OWNER_NAME_MISSING));
}
}
}
}
}
18
Source : AbstractSetAttributesPlatformMessageHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
public abstract clreplaced AbstractSetAttributesPlatformMessageHandler<B> implements ContextualRequestMessageHandler<B> {
public static final String MESSAGE_TYPE = Capability.CMD_SET_ATTRIBUTES;
public static final String ERR_UNDEFINED_CAPABILTY_CODE = "error.capability.undefined";
public static final String ERR_UNDEFINED_CAPABILITY_MSG = "No capability is defined for: ";
public static final String ERR_UNDEFINED_ATTRIBUTE_CODE = "error.attribute.undefined";
public static final String ERR_UNDEFINED_ATTRIBUTE_MSG = "No attribute defined with name: ";
public static final String ERR_ATTRIBUTE_NOTWRITABLE_CODE = "error.attribute.not_writable";
public static final String ERR_ATTRIBUTE_NOTWRITABLE_MSG = "Attribute is not writable: ";
private final CapabilityRegistry capabilityRegistry;
private final BeanAttributesTransformer<B> beanTransformer;
protected final PlatformMessageBus platformBus;
protected final PlacePopulationCacheManager populationCacheMgr;
protected AbstractSetAttributesPlatformMessageHandler(CapabilityRegistry capabilityRegistry, BeanAttributesTransformer<B> beanTransformer, PlatformMessageBus platformBus, PlacePopulationCacheManager populationCacheMgr) {
this.capabilityRegistry = capabilityRegistry;
this.beanTransformer = beanTransformer;
this.platformBus = platformBus;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public String getMessageType() {
return MESSAGE_TYPE;
}
protected void replacedertAccessible(B context, PlatformMessage msg) {
if (context == null) {
throw new ErrorEventException(Errors.notFound(msg.getDestination()));
}
}
@Override
public MessageBody handleRequest(B context, PlatformMessage msg) {
Utils.replacedertNotNull(context, "No context found, the object identified does not exist!");
MessageBody request = msg.getValue();
Map<String, Object> attributes = request.getAttributes();
ErrorEvent error = validateSettableAttributes(attributes);
if (error != null) {
return error;
}
Map<String, Object> beanAttributes = beanTransformer.transform(context);
Map<String, Object> changes = filterOnlyChanges(beanAttributes, attributes);
beforeSave(context, changes);
if (!changes.isEmpty()) {
Map<String, Object> oldAttributes = beanTransformer.merge(context, changes);
save(context);
afterSave(context, oldAttributes);
sendValueChangeEvent(context, msg, changes);
}
return MessageBody.emptyMessage();
}
// Note: The context object has not had changes merged at this point.
protected void beforeSave(B context, Map<String, Object> changes) {
// Do nothing by default.
}
protected abstract void save(B bean);
// Note: The context object has had changes merged at this point.
protected void afterSave(B context, Map<String, Object> oldAttributes) {
// Do nothing by default.
}
private Map<String, Object> filterOnlyChanges(final Map<String, Object> beanAttributes, final Map<String, Object> incomingAttributes) {
return MapUtil.filterChanges(beanAttributes, incomingAttributes);
}
protected void sendValueChangeEvent(B context, PlatformMessage request, Map<String, Object> changes) {
sendValueChangeEventForPlace(request, changes, request.getPlaceId());
}
protected void sendValueChangeEventForPlace(PlatformMessage request, Map<String, Object> changes, String placeId) {
MessageBody body = MessageBody.buildMessage(Capability.EVENT_VALUE_CHANGE, changes);
PlatformMessage msg = PlatformMessage.buildBroadcast(body, request.getDestination()).withPlaceId(placeId).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeId)).create();
platformBus.send(msg);
}
protected ErrorEvent validateSettableAttributes(Map<String, Object> attributes) {
for (String key : attributes.keySet()) {
if (!Utils.isNamespaced(key)) {
continue;
}
CapabilityDefinition capDef = capabilityRegistry.getCapabilityDefinitionByNamespace(Utils.getNamespace(key));
if (capDef == null) {
return ErrorEvent.fromCode(ERR_UNDEFINED_CAPABILTY_CODE, ERR_UNDEFINED_CAPABILITY_MSG + Utils.getNamespace(key));
}
AttributeDefinition attrDef = capDef.getAttributes().get(key);
if (attrDef == null) {
return ErrorEvent.fromCode(ERR_UNDEFINED_ATTRIBUTE_CODE, ERR_UNDEFINED_ATTRIBUTE_MSG + key);
}
if (!attrDef.isWritable()) {
return ErrorEvent.fromCode(ERR_ATTRIBUTE_NOTWRITABLE_CODE, ERR_ATTRIBUTE_NOTWRITABLE_MSG + key);
}
}
return null;
}
}
18
Source : DirectMessageHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
public abstract clreplaced DirectMessageHandler {
private static final Logger log = LoggerFactory.getLogger(DirectMessageHandler.clreplaced);
private final PlatformBusService platformBus;
private final Serializer<PlatformMessage> platformMessageSerializer = JSON.createSerializer(PlatformMessage.clreplaced);
private final Serializer<HubMessage> hubMessageSerializer = JSON.createSerializer(HubMessage.clreplaced);
private final PlacePopulationCacheManager populationCacheMgr;
protected DirectMessageHandler(PlatformBusService platformBus, PlacePopulationCacheManager populationCacheMgr) {
this.platformBus = platformBus;
this.populationCacheMgr = populationCacheMgr;
}
public abstract String supportsMessageType();
public void handle(Session session, PlatformMessage msg) {
if (!supportsMessageType().equals(msg.getMessageType())) {
return;
}
doHandle(session, msg);
}
protected abstract void doHandle(Session session, PlatformMessage msg);
protected void authorized(Session session, Model m, String correlationId) {
authorized(session, m.getAddress(), HubModel.getPlace(m), correlationId);
}
protected void authorized(Session session, Hub hub, String correlationId) {
authorized(session, Address.fromString(hub.getAddress()), String.valueOf(hub.getPlace()), correlationId);
}
private void authorized(Session session, Address hubAddress, String placeId, String correlationId) {
if (!placeId.equals(session.getActivePlace())) {
SessionUtil.setPlace(placeId, session);
}
updateSessionState(session, State.AUTHORIZED);
updateUnauthorizedReason(session, null);
sendToHub(session, PlatformMessage.buildMessage(MessageBody.buildMessage(MessageConstants.MSG_HUB_AUTHORIZED_EVENT, Collections.<String, Object>emptyMap()), Address.platformService(PlatformConstants.SERVICE_HUB), hubAddress).withPlaceId(placeId).withCorrelationId(correlationId).create());
}
protected void sendToHub(Session session, PlatformMessage msg) {
byte[] payload = platformMessageSerializer.serialize(msg);
byte[] message = hubMessageSerializer.serialize(HubMessage.createPlatform(payload));
if (session.getChannel().isActive()) {
session.sendMessage(message);
} else {
log.warn("discarding message {} disconnected session {}", msg, session.getClientToken());
}
}
protected void sendToPlatform(PlatformMessage msg) {
platformBus.placeMessageOnPlatformBus(msg);
}
protected void updateSessionState(Session session, State newState) {
HubSession hubSession = (HubSession) session;
if (hubSession.getUnauthReason() == UnauthorizedReason.UNAUTHENTICATED) {
throw new IllegalStateException("Can't change the state of an unauthenticated hub");
}
if (session.getChannel().isOpen()) {
hubSession.setState(newState);
}
}
protected void updateUnauthorizedReason(Session session, UnauthorizedReason reason) {
if (session.getChannel().isOpen()) {
((HubSession) session).setUnauthReason(reason);
}
}
protected PlacePopulationCacheManager getPlacePopulationCacheManager() {
return populationCacheMgr;
}
}
18
Source : TestDeviceDriverEvents.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
/**
*/
@Mocks({ DeviceDAO.clreplaced, PersonDAO.clreplaced, PersonPlacereplacedocDAO.clreplaced, PlaceDAO.clreplaced, PlacePopulationCacheManager.clreplaced })
public clreplaced TestDeviceDriverEvents extends IrisMockTestCase {
DeviceDriver driver;
ContextualEventHandler<DriverEvent> eventHandler1;
ContextualEventHandler<DriverEvent> eventHandler2;
PlatformDeviceDriverContext context;
@Inject
PlacePopulationCacheManager populationCacheMgr;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
eventHandler1 = EasyMock.createMock(ContextualEventHandler.clreplaced);
eventHandler2 = EasyMock.createMock(ContextualEventHandler.clreplaced);
driver = Drivers.builder().withName("Test").withMatcher(Predicates.alwaysTrue()).withPopulations(ImmutableList.<String>of(Population.NAME_GENERAL, Population.NAME_BETA, Population.NAME_QA)).addDriverEventHandler(DevicereplacedociatedEvent.clreplaced, eventHandler1).addDriverEventHandler(DeviceConnectedEvent.clreplaced, eventHandler1).addDriverEventHandler(DeviceDisconnectedEvent.clreplaced, eventHandler1).addDriverEventHandler(DeviceDisreplacedociatedEvent.clreplaced, eventHandler1).addDriverEventHandler(DevicereplacedociatedEvent.clreplaced, eventHandler2).addDriverEventHandler(DeviceConnectedEvent.clreplaced, eventHandler2).addDriverEventHandler(DeviceDisconnectedEvent.clreplaced, eventHandler2).addDriverEventHandler(DeviceDisreplacedociatedEvent.clreplaced, eventHandler2).addCapabilityDefinition(new CapabilityDefinition("Device", "dev", "base", "", ImmutableMap.of(), ImmutableMap.of(), ImmutableMap.of())).create(true);
EasyMock.expect(populationCacheMgr.getPopulationByPlaceId(EasyMock.anyObject(UUID.clreplaced))).andReturn(Population.NAME_GENERAL).anyTimes();
context = new PlatformDeviceDriverContext(Fixtures.createDevice(), driver, populationCacheMgr);
context.setAttributeValue(DeviceConnectionCapability.KEY_STATE.valueOf(DeviceConnectionCapability.STATE_ONLINE));
context.clearDirty();
}
@Override
public void replay() {
super.replay();
EasyMock.replay(eventHandler1, eventHandler2);
}
@Override
public void verify() {
EasyMock.verify(eventHandler1, eventHandler2);
super.verify();
}
@Test
public void testreplacedociated() throws Exception {
DriverEvent event = DriverEvent.createreplacedociated(AttributeMap.emptyMap());
EasyMock.expect(eventHandler1.handleEvent(context, event)).andReturn(true).once();
EasyMock.expect(eventHandler2.handleEvent(context, event)).andReturn(true).once();
EasyMock.expect(eventHandler1.handleEvent(context, event)).andReturn(false).once();
EasyMock.expect(eventHandler2.handleEvent(context, event)).andReturn(false).once();
replay();
driver.handleDriverEvent(event, context);
driver.handleDriverEvent(event, context);
verify();
}
/**
* Each listener should be notified regardless of exceptions being thrown
* @throws Exception
*/
@Test
public void testreplacedociatedThrowsException() throws Exception {
DriverEvent event = DriverEvent.createreplacedociated(AttributeMap.emptyMap());
EasyMock.expect(eventHandler1.handleEvent(context, event)).andThrow(new RuntimeException("BOOM")).once();
EasyMock.expect(eventHandler2.handleEvent(context, event)).andThrow(new RuntimeException("BOOM")).once();
replay();
driver.handleDriverEvent(event, context);
verify();
}
@Test
public void testAllEvents() throws Exception {
DriverEvent replacedociated = DriverEvent.createreplacedociated(AttributeMap.emptyMap());
DriverEvent connected = DriverEvent.createConnected(0);
DriverEvent disconnected = DriverEvent.createDisconnected(0);
DriverEvent disreplacedociated = DriverEvent.createDisreplacedociated();
EasyMock.expect(eventHandler1.handleEvent(context, replacedociated)).andReturn(true).once();
EasyMock.expect(eventHandler2.handleEvent(context, replacedociated)).andReturn(true).once();
EasyMock.expect(eventHandler1.handleEvent(context, connected)).andReturn(true).once();
EasyMock.expect(eventHandler2.handleEvent(context, connected)).andReturn(true).once();
EasyMock.expect(eventHandler1.handleEvent(context, disconnected)).andReturn(true).once();
EasyMock.expect(eventHandler2.handleEvent(context, disconnected)).andReturn(true).once();
EasyMock.expect(eventHandler1.handleEvent(context, disreplacedociated)).andReturn(true).once();
EasyMock.expect(eventHandler2.handleEvent(context, disreplacedociated)).andReturn(true).once();
replay();
driver.handleDriverEvent(replacedociated, context);
driver.handleDriverEvent(connected, context);
driver.handleDriverEvent(disconnected, context);
driver.handleDriverEvent(disreplacedociated, context);
verify();
}
}
17
Source : IpcdServiceEventListener.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced IpcdServiceEventListener implements PlatformBusListener {
private static final Logger logger = LoggerFactory.getLogger(IpcdServiceEventListener.clreplaced);
private final SessionRegistry registry;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public IpcdServiceEventListener(SessionRegistry registry, PlacePopulationCacheManager populationCacheMgr) {
this.registry = registry;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public void onMessage(ClientToken ct, PlatformMessage msg) {
switch(msg.getMessageType()) {
case IpcdService.DeviceClaimedEvent.NAME:
onClaimed(msg);
break;
case IpcdService.DeviceRegisteredEvent.NAME:
onRegistered(msg);
break;
case IpcdService.DeviceUnregisteredEvent.NAME:
onUnregistered(msg);
break;
default:
break;
}
}
private void onClaimed(PlatformMessage msg) {
MessageBody body = msg.getValue();
logger.trace("handling claim event: [{}]", body);
String protocolAddress = IpcdService.DeviceClaimedEvent.getProtocolAddress(body);
IpcdSession session = getSession(protocolAddress);
if (session == null) {
logger.debug("dropping claim event for [{}], no IPCD session found in the registry", protocolAddress);
return;
}
String curPlaceId = IpcdService.DeviceClaimedEvent.getPlaceId(body);
session.claim(IpcdService.DeviceClaimedEvent.getAccountId(body), curPlaceId, lookupPopulationByPlace(curPlaceId));
}
private void onRegistered(PlatformMessage msg) {
MessageBody body = msg.getValue();
logger.trace("handling register event: [{}]", body);
String protocolAddress = IpcdService.DeviceRegisteredEvent.getProtocolAddress(body);
IpcdSession session = getSession(protocolAddress);
if (session == null) {
logger.debug("dropping register event for [{}], no IPCD session found in the registry", protocolAddress);
return;
}
String curPlaceId = IpcdService.DeviceRegisteredEvent.getPlaceId(body);
session.register(IpcdService.DeviceRegisteredEvent.getAccountId(body), curPlaceId, lookupPopulationByPlace(curPlaceId), IpcdService.DeviceRegisteredEvent.getDriverAddress(body));
}
private void onUnregistered(PlatformMessage msg) {
MessageBody body = msg.getValue();
logger.trace("handling unregister event: [{}]", body);
String protocolAddress = IpcdService.DeviceUnregisteredEvent.getProtocolAddress(body);
IpcdSession session = getSession(protocolAddress);
if (session == null) {
logger.debug("dropping unregister event for [{}], no IPCD session found in the registry", protocolAddress);
return;
}
session.unregister();
}
private IpcdSession getSession(String protocolAddress) {
if (StringUtils.isBlank(protocolAddress)) {
return null;
}
ClientToken tok = IpcdClientToken.fromProtocolAddress(protocolAddress);
Session session = registry.getSession(tok);
if (!(session instanceof IpcdSession)) {
return null;
}
return (IpcdSession) session;
}
private String lookupPopulationByPlace(String curPlaceId) {
return populationCacheMgr.getPopulationByPlaceId(curPlaceId);
}
}
17
Source : SetPreferencesHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced SetPreferencesHandler extends BaseClientRequestHandler {
public static final String NAME_EXECUTOR = "executor.setpreferences";
public static final ErrorEvent ACTIVE_PLACE_NOT_SET = Errors.fromCode(CODE_PLACE_ACTIVE_NOTSET, "No active place is currently set");
private static final Set<String> VALID_PREFERENCE_ATTRIBUTES = Preferences.TYPE.asObject().getAttributes().keySet();
private final PreferencesDAO preferencesDao;
private final PlatformMessageBus messageBus;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public SetPreferencesHandler(PreferencesDAO preferencesDao, PlatformMessageBus messageBus, @Named(NAME_EXECUTOR) Executor executor, PlacePopulationCacheManager populationCacheMgr) {
super(executor);
this.preferencesDao = preferencesDao;
this.messageBus = messageBus;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public String getRequestType() {
return SetPreferencesRequest.NAME;
}
@Override
protected Address address() {
return SessionService.ADDRESS;
}
@Override
protected MessageBody doHandle(ClientMessage request, Session session) {
validate(request, session);
UUID personUuid = session.getClient().getPrincipalId();
UUID placeUuid = UUID.fromString(session.getActivePlace());
Map<String, Object> prefs = SetPreferencesRequest.getPrefs(request.getPayload());
Map<String, Object> completePrefs = preferencesDao.findById(personUuid, placeUuid);
if (completePrefs == null) {
completePrefs = prefs;
} else {
completePrefs.putAll(prefs);
}
preferencesDao.merge(personUuid, placeUuid, prefs);
emitPreferencesChangedEvent(personUuid, placeUuid, populationCacheMgr.getPopulationByPlaceId(placeUuid), completePrefs);
return SetPreferencesResponse.instance();
}
private void validate(ClientMessage request, Session session) {
Client client = session.getClient();
if (client == null) {
throw new IllegalStateException("client cannot be null");
}
UUID personUuid = client.getPrincipalId();
if (personUuid == null) {
throw new IllegalStateException("principalId cannot be null");
}
String placeId = session.getActivePlace();
if (isEmpty(placeId)) {
throw new ErrorEventException(ACTIVE_PLACE_NOT_SET);
}
Map<String, Object> prefs = SetPreferencesRequest.getPrefs(request.getPayload());
Errors.replacedertValidRequest(difference(prefs.keySet(), VALID_PREFERENCE_ATTRIBUTES).isEmpty(), SetPreferencesRequest.ATTR_PREFS + " contains unexpected keys");
Preferences preferences = new Preferences(prefs);
if (preferences.getDashboardCards() != null) {
// This prevents unexpected cards
Set<String> cards = new HashSet<>();
for (Map<String, Object> card : preferences.getDashboardCards()) {
try {
CardPreference cp = new CardPreference(card);
Errors.replacedertValidRequest(cards.add(cp.getServiceName()), "Duplicate dashboard card [" + cp.getServiceName() + "]");
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("is not a valid member of the enumeration set")) {
Errors.replacedertValidRequest(false, "Unrecognized dashboard card [" + card.get(CardPreference.ATTR_SERVICENAME) + "]");
} else {
throw e;
}
}
}
}
}
private void emitPreferencesChangedEvent(UUID personUuid, UUID placeUuid, String population, Map<String, Object> completePrefs) {
MessageBody body = PreferencesChangedEvent.builder().withPrefs(completePrefs).build();
PlatformMessage message = PlatformMessage.buildEvent(body, address()).withActor(Address.platformService(personUuid, PersonCapability.NAMESPACE)).withPlaceId(placeUuid).withPopulation(population).create();
messageBus.send(message);
}
}
17
Source : IrisNettyMessageHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
public clreplaced IrisNettyMessageHandler implements DeviceMessageHandler<String> {
private static final String SESSION_SERVICE_ADDRESS = Addresses.toServiceAddress(SessionService.NAMESPACE);
private static final Counter NUM_VIDEO_CACHE_RESPONSE_HIT = IrisMetrics.metrics("client.bridge").counter("video.cached.response.hit");
private static final Counter NUM_VIDEO_CACHE_RESPONSE_MISS = IrisMetrics.metrics("client.bridge").counter("video.cached.response.miss");
private static final MessageBody EMPTY_LIST_RECORDINGS_RESPONSE = VideoService.ListRecordingsResponse.builder().withRecordings(Collections.emptyList()).build();
private static final Logger logger = LoggerFactory.getLogger(IrisNettyMessageHandler.clreplaced);
private final PlatformBusService platformBusService;
private final Authorizer authorizer;
private final IrisNettyMessageUtil messageUtil;
private final ClientRequestDispatcher clientRequestDispatcher;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public IrisNettyMessageHandler(PlatformBusService platformBusService, Authorizer authorizer, IrisNettyMessageUtil messageUtil, ClientRequestDispatcher clientRequestDispatcher, PlacePopulationCacheManager populationCacheMgr) {
this.platformBusService = platformBusService;
this.authorizer = authorizer;
this.messageUtil = messageUtil;
this.clientRequestDispatcher = clientRequestDispatcher;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public String handleMessage(Session session, String message) {
logger.debug("Received message from client [{}]", message);
Client client = session.getClient();
if (client == null || !client.isAuthenticated()) {
session.disconnect(Constants.SESSION_EXPIRED_STATUS);
return null;
}
ClientMessage clientMsg = JSON.fromJson(message, ClientMessage.clreplaced);
if (clientMsg.isRequest()) {
session.getClient().requestReceived();
}
/*
* try(...) - Uses Java 1.7+ Automatic Resource Management eliminating need for finally block to
* manage closeable resources. All resources that implement AutoCloseable will be automatically
* closed as necessary without a finally block. e.g. MdcContextReference
*/
try (MdcContextReference context = BridgeMdcUtil.captureAndInitializeContext(session, clientMsg)) {
if (SESSION_SERVICE_ADDRESS.equals(clientMsg.getDestination())) {
clientRequestDispatcher.submit(clientMsg, session);
return null;
}
Address actor = Address.platformService(session.getAuthorizationContext().getPrincipal().getUserId(), PersonCapability.NAMESPACE);
PlatformMessage platformMessage = null;
try {
platformMessage = messageUtil.convertClientToPlatform(clientMsg, session, actor, populationCacheMgr);
} catch (Exception ex) {
ErrorEvent err = Errors.fromException(ex);
// Return error response instead of disconnecting socket which would cause a reconnect
return createResponseFromErrorEvent(session, clientMsg, err);
}
if (VideoService.ListRecordingsRequest.NAME.equals(clientMsg.getType())) {
MessageBody result = EMPTY_LIST_RECORDINGS_RESPONSE;
NUM_VIDEO_CACHE_RESPONSE_HIT.inc();
PlatformMessage cachedResponse = PlatformMessage.createResponse(platformMessage, result);
return JSON.toJson(messageUtil.convertPlatformToClient(cachedResponse));
}
try {
if (authorizer.isAuthorized(session.getAuthorizationContext(), session.getActivePlace(), platformMessage)) {
logger.debug("Placing message on platform bus [{}] for place id [{}] and population [{}]", platformMessage, platformMessage.getPlaceId(), platformMessage.getPopulation());
platformBusService.placeMessageOnPlatformBus(platformMessage);
} else {
logger.debug("Placing unauthorized error message on platform bus");
platformBusService.placeMessageOnPlatformBus(PlatformMessage.createResponse(platformMessage, AuthzUtil.createUnauthorizedEvent()));
}
} catch (UnknownSessionException use) {
session.disconnect(Constants.SESSION_EXPIRED_STATUS);
} catch (Exception e) {
ErrorEvent err = Errors.fromException(e);
return createResponseFromErrorEvent(session, clientMsg, err);
}
return null;
}
}
private String createResponseFromErrorEvent(Session session, ClientMessage clientMsg, ErrorEvent err) {
Address dest = Address.fromString(messageUtil.buildId(session.getClientToken().getRepresentation()));
ClientMessage.Builder builder = ClientMessage.builder().withPayload(err).withSource(SESSION_SERVICE_ADDRESS).withDestination(dest.getRepresentation());
if (!StringUtils.isBlank(clientMsg.getCorrelationId())) {
builder.withCorrelationId(clientMsg.getCorrelationId());
}
ClientMessage response = builder.create();
return JSON.toJson(response);
}
}
17
Source : VoicePlaceSelectionHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced VoicePlaceSelectionHandler implements PlaceSelectionHandler {
private static final Logger logger = LoggerFactory.getLogger(VoicePlaceSelectionHandler.clreplaced);
private final PlatformBusClient busClient;
private final VoiceBridgeConfig config;
private final Address bridgeAddress;
private final VoiceBridgeMetrics metrics;
private final String replacedistant;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public VoicePlaceSelectionHandler(PlatformMessageBus bus, @Named(VoiceBridgeConfig.NAME_EXECUTOR) ExecutorService executor, VoiceBridgeConfig config, @Named(VoiceBridgeConfig.NAME_BRIDGEADDRESS) Address bridgeAddress, VoiceBridgeMetrics metrics, @Named(VoiceBridgeConfig.NAME_BRIDGEreplacedISTANT) String replacedistant, PlacePopulationCacheManager populationCacheMgr) {
this.busClient = new PlatformBusClient(bus, executor, ImmutableSet.of(AddressMatchers.equals(bridgeAddress)));
this.bridgeAddress = bridgeAddress;
this.config = config;
this.metrics = metrics;
this.replacedistant = replacedistant;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public void placeAuthorized(UUID placeId) {
long startTime = System.nanoTime();
PlatformMessage msg = PlatformMessage.buildRequest(VoiceService.StartPlaceRequest.builder().withreplacedistant(replacedistant).build(), bridgeAddress, Address.platformService(VoiceService.NAMESPACE)).withCorrelationId(IrisUUID.randomUUID().toString()).withPlaceId(placeId).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeId)).withTimeToLive((int) config.getRequestTimeoutMs()).create();
try {
busClient.request(msg).get(config.getRequestTimeoutMs(), TimeUnit.MILLISECONDS);
metrics.timeServiceSuccess(msg.getMessageType(), startTime);
} catch (Exception e) {
logger.warn("failed to start place {}", placeId, e);
metrics.timeServiceFailure(msg.getMessageType(), startTime);
}
}
@Override
public void placeDeauthorized(UUID placeId) {
long startTime = System.nanoTime();
PlatformMessage msg = PlatformMessage.buildRequest(VoiceService.StopPlaceRequest.builder().withreplacedistant(replacedistant).build(), bridgeAddress, Address.platformService(VoiceService.NAMESPACE)).withCorrelationId(IrisUUID.randomUUID().toString()).withPlaceId(placeId).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeId)).withTimeToLive((int) config.getRequestTimeoutMs()).create();
try {
busClient.request(msg).get(config.getRequestTimeoutMs(), TimeUnit.MILLISECONDS);
metrics.timeServiceSuccess(msg.getMessageType(), startTime);
} catch (Exception e) {
logger.warn("failed to stop place {}", placeId, e);
metrics.timeServiceFailure(msg.getMessageType(), startTime);
}
}
}
17
Source : TestZigbeeSender.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Mocks({ PlacePopulationCacheManager.clreplaced })
public clreplaced TestZigbeeSender extends IrisMockTestCase {
private final static ByteOrder BYTE_ORDER = ByteOrder.LITTLE_ENDIAN;
private final static int CS = ZigbeeMessage.Zcl.CLUSTER_SPECIFIC;
private final static int DDR = ZigbeeMessage.Zcl.DISABLE_DEFAULT_RESPONSE;
@Inject
private PlacePopulationCacheManager mockPopulationCacheMgr;
private GroovyScriptEngine engine;
private Script script;
private DeviceDriverContext context;
private InMemoryProtocolMessageBus bus;
private ZigbeeProtocol protocol;
private final byte[] testBytes = new byte[] { 0x08, 0x0f, 0x10, 0x17, 0x2a, (byte) 0xff };
private Address driverAddress = Fixtures.createDeviceAddress();
private Address protocolAddress = Address.protocolAddress("ZIGB", new byte[] { (byte) 0x04 });
@SuppressWarnings("unchecked")
@Before
public void setUp() throws Exception {
protocol = ZigbeeProtocol.INSTANCE;
Device device = Fixtures.createDevice();
device.setAddress(driverAddress.getRepresentation());
device.setProtocolAddress(protocolAddress.getRepresentation());
device.setProtocolAttributes(ZigbeeFixtures.createProtocolAttributes());
DeviceDriver driver = EasyMock.createNiceMock(DeviceDriver.clreplaced);
EasyMock.expect(driver.getDefinition()).andReturn(DeviceDriverDefinition.builder().withName("TestDriver").create()).anyTimes();
EasyMock.expect(driver.getBaseAttributes()).andReturn(AttributeMap.emptyMap()).anyTimes();
EasyMock.replay(driver);
ServiceLocator.init(GuiceServiceLocator.create(Bootstrap.builder().withModuleClreplacedes(InMemoryMessageModule.clreplaced).withModules(new AbstractIrisModule() {
@Override
protected void configure() {
bind(ZigbeeContext.clreplaced);
}
@Provides
public PersonDAO personDao() {
return EasyMock.createMock(PersonDAO.clreplaced);
}
@Provides
public PersonPlacereplacedocDAO personPlacereplacedocDao() {
return EasyMock.createMock(PersonPlacereplacedocDAO.clreplaced);
}
}).build().bootstrap()));
bus = ServiceLocator.getInstance(InMemoryProtocolMessageBus.clreplaced);
engine = new GroovyScriptEngine(new ClreplacedpathResourceConnector(this.getClreplaced()));
context = new PlatformDeviceDriverContext(device, driver, mockPopulationCacheMgr);
script = engine.createScript("TestZigbeeSend.gscript", new Binding());
script.run();
script.setProperty("Zigbee", ServiceLocator.getInstance(ZigbeeContext.clreplaced));
GroovyContextObject.setContext(context);
}
@After
public void tearDown() {
ServiceLocator.destroy();
}
@Test
public void testSendFromZigbeeWithDefaults() throws Exception {
script.invokeMethod("sendFromZigbeeWithDefaults", new Object[0]);
checkMessage(bus.take(), 4, 7, 0x0104, 1, CS | DDR, new byte[0]);
}
@Test
public void testSendFromZigbeeWithEverything() throws Exception {
script.invokeMethod("sendFromZigbeeWithEverything", new Object[0]);
checkMessage(bus.take(), 4, 7, 0x0105, 1, 0, testBytes);
}
@Test
public void testSendFromZigbeeUsingEndpointClusterSpecific() throws Exception {
script.invokeMethod("sendFromZigbeeUsingEndpointClusterSpecific", new Object[0]);
checkMessage(bus.take(), 4, 7, 0x0104, 1, CS | DDR, testBytes);
}
@Test
public void testSendFromZigbeeUsingEndpointGeneral() throws Exception {
script.invokeMethod("sendFromZigbeeUsingEndpointGeneral", new Object[0]);
checkMessage(bus.take(), 4, 7, 0x0104, 1, DDR, testBytes);
}
@Test
public void testSendFromZigbeeUsingEndpointGeneralNoBytes() throws Exception {
script.invokeMethod("sendFromZigbeeUsingEndpointGeneralNoBytes", new Object[0]);
checkMessage(bus.take(), 4, 7, 0x0104, 1, DDR, new byte[0]);
}
@Test
public void testSendFromZigbeeUsingEndpointSendDefaultResponse() throws Exception {
script.invokeMethod("sendFromZigbeeUsingEndpointSendDefaultResponse", new Object[0]);
checkMessage(bus.take(), 4, 7, 0x0104, 1, CS, testBytes);
}
@Test
public void testSendFromZigbeeUsingEndpointSendDefaultResponseFalseNoBytes() throws Exception {
script.invokeMethod("sendFromZigbeeUsingEndpointSendDefaultResponseFalseNoBytes", new Object[0]);
checkMessage(bus.take(), 4, 7, 0x0104, 1, CS | DDR, new byte[0]);
}
@Test
public void testSendFromZigbeeUsingEndpointFlags() throws Exception {
script.invokeMethod("sendFromZigbeeUsingEndpointFlags", new Object[0]);
checkMessage(bus.take(), 4, 7, 0x0104, 1, 7, testBytes);
}
@Test
public void testSendFromZigbeeUsingEndpointFlagsNoBytes() throws Exception {
script.invokeMethod("sendFromZigbeeUsingEndpointFlagsNoBytes", new Object[0]);
checkMessage(bus.take(), 4, 7, 0x0104, 1, 9, new byte[0]);
}
@Test
public void testSendFromZigbeeUsingCustomEndpoint() throws Exception {
script.invokeMethod("sendFromZigbeeUsingCustomEndpoint", new Object[0]);
checkMessage(bus.take(), 4, 7, 0x0111, 3, 10, testBytes);
}
@Test
public void testSendFromZigbeeUsingCluster() throws Exception {
script.invokeMethod("sendFromZigbeeUsingCluster", new Object[0]);
checkMessage(bus.take(), OnOff.CLUSTER_ID, OnOff.On.ID, 0x0104, 1, CS | DDR, new byte[0]);
}
@Test
public void testSendGeneralCommandUsingCluster() throws Exception {
script.invokeMethod("sendGeneralCommandUsingCluster", new Object[0]);
ZclData data = ZclData.builder().set8BitEnum(Fan.FAN_MODE_HIGH).create();
ZclWriteAttributeRecord record = ZclWriteAttributeRecord.builder().setAttributeIdentifier(Fan.ATTR_FAN_MODE).setAttributeData(data).create();
ZclWriteAttributes message = ZclWriteAttributes.builder().setAttributes(new ZclWriteAttributeRecord[] { record }).create();
checkMessage(bus.take(), Fan.CLUSTER_ID, General.ZclWriteAttributes.ID, 0x0104, 1, DDR, message.toBytes(BYTE_ORDER));
}
@Test
public void testSendWriteAttributesUsingHelper() throws Exception {
ZclData data = ZclData.builder().set8BitEnum(Fan.FAN_MODE_HIGH).create();
ZclWriteAttributeRecord record = ZclWriteAttributeRecord.builder().setAttributeIdentifier(Fan.ATTR_FAN_MODE).setAttributeData(data).create();
ZclWriteAttributes message = ZclWriteAttributes.builder().setAttributes(new ZclWriteAttributeRecord[] { record }).create();
script.invokeMethod("sendWriteAttributesUsingHelper", new Object[0]);
checkMessage(bus.take(), Fan.CLUSTER_ID, General.ZclWriteAttributes.ID, 0x0104, 1, DDR, message.toBytes(BYTE_ORDER));
}
@Test
public void testSendWriteAttributesUsingMap() throws Exception {
ZclData data = ZclData.builder().set8BitEnum(Fan.FAN_MODE_HIGH).create();
ZclWriteAttributeRecord record = ZclWriteAttributeRecord.builder().setAttributeIdentifier(Fan.ATTR_FAN_MODE).setAttributeData(data).create();
ZclData data2 = ZclData.builder().set8BitEnum(Fan.FAN_MODE_SEQUENCE_LOW_HIGH).create();
ZclWriteAttributeRecord record2 = ZclWriteAttributeRecord.builder().setAttributeIdentifier(Fan.ATTR_FAN_MODE_SEQUENCE).setAttributeData(data2).create();
ZclWriteAttributes message = ZclWriteAttributes.builder().setAttributes(new ZclWriteAttributeRecord[] { record, record2 }).create();
script.invokeMethod("sendWriteAttributesUsingMap", new Object[0]);
checkMessage(bus.take(), Fan.CLUSTER_ID, General.ZclWriteAttributes.ID, 0x0104, 1, DDR, message.toBytes(BYTE_ORDER));
}
@Test
public void testSendZdpByIdAndByteArray() throws Exception {
script.invokeMethod("sendZdpByIdAndByteArray", new Object[0]);
checkZdpMessage(bus.take(), 11);
}
private void checkMessage(ProtocolMessage msg, int clusterId, int messageId, int profileId, int endpoint, int flags, byte[] bytes) {
replacedert.replacedertEquals(driverAddress, msg.getSource());
replacedert.replacedertEquals(protocolAddress, msg.getDestination());
ZigbeeMessage.Protocol zigMsg = msg.getValue(protocol);
replacedert.replacedertEquals(true, ZigbeeProtocol.isZcl(zigMsg));
replacedert.replacedertEquals(false, ZigbeeProtocol.isZdp(zigMsg));
ZigbeeMessage.Zcl zclMsg = ZigbeeProtocol.getZclMessage(zigMsg);
replacedert.replacedertEquals(profileId, zclMsg.getProfileId());
replacedert.replacedertEquals(flags, zclMsg.getFlags());
replacedert.replacedertEquals(endpoint, zclMsg.getEndpoint());
replacedert.replacedertEquals(clusterId, zclMsg.getClusterId());
replacedert.replacedertEquals(messageId, zclMsg.getZclMessageId());
replacedert.replacedertArrayEquals(bytes, zclMsg.getPayload());
}
private void checkZdpMessage(ProtocolMessage msg, int messageId) {
replacedert.replacedertEquals(driverAddress, msg.getSource());
replacedert.replacedertEquals(protocolAddress, msg.getDestination());
ZigbeeMessage.Protocol zigMsg = msg.getValue(protocol);
replacedert.replacedertEquals(false, ZigbeeProtocol.isZcl(zigMsg));
replacedert.replacedertEquals(true, ZigbeeProtocol.isZdp(zigMsg));
ZigbeeMessage.Zdp zdpMsg = ZigbeeProtocol.getZdpMessage(zigMsg);
replacedert.replacedertEquals(messageId, zdpMsg.getZdpMessageId());
replacedert.replacedertArrayEquals(testBytes, zdpMsg.getPayload());
}
public static void printBytes(String msg, byte[] bytes) {
StringBuffer sb = new StringBuffer("[");
for (byte bite : bytes) {
sb.append(String.valueOf(bite)).append(", ");
}
sb.append("]");
System.out.println(msg + ": " + sb);
}
}
17
Source : GroovyDriverTestCase.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
/**
*/
@Mocks({ DeviceDAO.clreplaced, PersonDAO.clreplaced, PersonPlacereplacedocDAO.clreplaced, PlaceDAO.clreplaced, PlacePopulationCacheManager.clreplaced })
@Modules({ CapabilityRegistryModule.clreplaced, MessagesModule.clreplaced })
public abstract clreplaced GroovyDriverTestCase extends IrisMockTestCase {
@Inject
protected GroovyDriverFactory factory;
@Inject
protected CapabilityRegistry registry;
@Inject
protected DeviceDAO mockDeviceDao;
@Inject
protected PlaceDAO mockPlaceDao;
@Inject
protected PlacePopulationCacheManager mockPopulationCacheMgr;
protected static String TMP_DIR = "build/tmp/groovy-driver";
protected Set<GroovyDriverPlugin> getPlugins() {
return ImmutableSet.of(new SchedulerPlugin(), new ControlProtocolPlugin(), new ZWaveProtocolPlugin());
}
protected GroovyScriptEngine scriptEngine() {
return new GroovyScriptEngine(new ClreplacedpathResourceConnector());
}
@Override
@Before
public void setUp() throws Exception {
super.setUp();
GroovyValidator.clear();
Capture<Device> deviceRef = Capture.newInstance();
EasyMock.expect(mockDeviceDao.save(EasyMock.capture(deviceRef))).andAnswer(() -> {
Device device = deviceRef.getValue().copy();
if (device.getId() == null) {
device.setId(UUID.randomUUID());
}
if (device.getCreated() == null) {
device.setCreated(new Date());
}
device.setModified(new Date());
return device;
}).anyTimes();
mockDeviceDao.updateDriverState(EasyMock.notNull(), EasyMock.notNull());
EasyMock.expectLastCall().anyTimes();
EasyMock.replay(mockDeviceDao);
}
@Override
protected void configure(Binder binder) {
binder.bind(new Key<Set<GroovyDriverPlugin>>() {
}).toInstance(getPlugins());
binder.bind(InMemoryPlatformMessageBus.clreplaced).in(Singleton.clreplaced);
binder.bind(InMemoryProtocolMessageBus.clreplaced).in(Singleton.clreplaced);
binder.bind(PlatformMessageBus.clreplaced).to(InMemoryPlatformMessageBus.clreplaced);
binder.bind(ProtocolMessageBus.clreplaced).to(InMemoryProtocolMessageBus.clreplaced);
Multibinder.newSetBinder(binder, CompilationCustomizer.clreplaced).addBinding().to(DriverCompilationCustomizer.clreplaced);
binder.bind(Scheduler.clreplaced).toInstance(new ExecutorScheduler(Executors.newScheduledThreadPool(1)));
}
@Provides
@Singleton
public BeanAttributesTransformer<Device> deviceAttributeTransformer(CapabilityRegistry capabilityRegistry) {
return new ReflectiveBeanAttributesTransformer<Device>(capabilityRegistry, new HashSet<String>(Arrays.asList("dev", "devadv", "base")), Device.clreplaced);
}
@Provides
@Singleton
public GroovyScriptEngine scriptEngine(Set<CompilationCustomizer> customizers) {
GroovyScriptEngine engine = scriptEngine();
for (CompilationCustomizer customizer : customizers) {
engine.getConfig().addCompilationCustomizers(customizer);
}
engine.getConfig().setScriptExtensions(ImmutableSet.of("driver", "capability", "groovy"));
return engine;
}
protected Device createDevice(DeviceDriver driver) {
Device device = Fixtures.createDevice();
device.setDrivername(driver.getDefinition().getName());
device.setDriverversion(driver.getDefinition().getVersion());
device.setCaps(driver.getBaseAttributes().get(Capability.KEY_CAPS));
device.setDevtypehint(driver.getBaseAttributes().get(DeviceCapability.KEY_DEVTYPEHINT));
device.setVendor(driver.getBaseAttributes().get(DeviceCapability.KEY_VENDOR));
device.setModel(driver.getBaseAttributes().get(DeviceCapability.KEY_MODEL));
device.setProtocol(driver.getBaseAttributes().get(DeviceAdvancedCapability.KEY_PROTOCOL));
device.setProtocolid(driver.getBaseAttributes().get(DeviceAdvancedCapability.KEY_PROTOCOLID));
return device;
}
}
17
Source : TestGroovyCapabilityDefinition.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
/**
*/
@Mocks({ PersonDAO.clreplaced, PersonPlacereplacedocDAO.clreplaced, PlacePopulationCacheManager.clreplaced, PlaceDAO.clreplaced })
@Modules({ CapabilityRegistryModule.clreplaced })
public clreplaced TestGroovyCapabilityDefinition extends IrisMockTestCase {
@Inject
CapabilityRegistry registry;
@Inject
private PlacePopulationCacheManager mockPopulationCacheMgr;
private GroovyScriptEngine engine;
private Script script;
private DeviceDriverContext context;
private DriverBinding binding;
private String accountId = String.valueOf(UUID.randomUUID());
private String placeId = String.valueOf(UUID.randomUUID());
protected CapabilityDefinition deviceCapability() {
return registry.getCapabilityDefinitionByNamespace(DeviceCapability.NAMESPACE);
}
@Override
@Before
public void setUp() throws Exception {
super.setUp();
AttributeMap attributes = AttributeMap.newMap();
attributes.set(DeviceCapability.KEY_DEVTYPEHINT, "device");
attributes.set(DeviceCapability.KEY_MODEL, "model");
attributes.set(DeviceCapability.KEY_VENDOR, "vendor");
Device device = Fixtures.createDevice();
device.setAccount(UUID.fromString(accountId));
device.setPlace(UUID.fromString(placeId));
device.setDevtypehint("device");
device.setModel("model");
device.setName("name");
device.setVendor("vendor");
engine = new GroovyScriptEngine(new ClreplacedpathResourceConnector(TestGroovyCapabilityDefinition.clreplaced));
context = new PlatformDeviceDriverContext(device, DeviceDriverDefinition.builder().withName("TestDriver").create(), new DeviceDriverStateHolder(attributes), mockPopulationCacheMgr);
binding = new DriverBinding(new StaticCapabilityRegistryImpl(Collections.singleton(deviceCapability())), null);
script = engine.createScript("TestGroovyCapabilityDefinition.gscript", binding);
script.setProperty(DeviceCapability.NAME, new GroovyCapabilityDefinition(deviceCapability(), binding));
script.run();
GroovyContextObject.setContext(context);
}
@Override
@After
public void tearDown() throws Exception {
// don't leak to the next test case
GroovyContextObject.clearContext();
super.tearDown();
}
@Test
public void testGetCapability() {
GroovyCapabilityDefinition context = (GroovyCapabilityDefinition) script.invokeMethod("getProperty", DeviceCapability.NAME);
replacedertEquals(deviceCapability(), context.getDefinition());
}
@Test
public void testGetAttribute() {
replacedertEquals(accountId, script.invokeMethod("getAttributeValue", new Object[] { DeviceCapability.NAME, "account" }));
replacedertEquals("device", script.invokeMethod("getAttributeValue", new Object[] { DeviceCapability.NAME, "devtypehint" }));
replacedertEquals("model", script.invokeMethod("getAttributeValue", new Object[] { DeviceCapability.NAME, "model" }));
replacedertEquals("name", script.invokeMethod("getAttributeValue", new Object[] { DeviceCapability.NAME, "name" }));
replacedertEquals(placeId, script.invokeMethod("getAttributeValue", new Object[] { DeviceCapability.NAME, "place" }));
replacedertEquals("vendor", script.invokeMethod("getAttributeValue", new Object[] { DeviceCapability.NAME, "vendor" }));
}
@Test
public void testSetAttribute() throws Exception {
// TODO make some properties in device base read-only (can't change id, placeId, etc)
script.invokeMethod("setAttributeValue", new Object[] { DeviceCapability.NAME, "name", "testing" });
replacedertEquals("testing", context.getAttributeValue(DeviceCapability.KEY_NAME));
}
@Test
public void testReadOnlyProperty() throws Exception {
try {
script.invokeMethod("setAttributeValue", new Object[] { DeviceCapability.NAME, "id", UUID.randomUUID() });
fail("Allowed a read-only attribute to be written");
} catch (Exception e) {
// expected
e.printStackTrace(System.out);
}
}
@Test
public void testGetProperty() {
replacedertEquals(deviceCapability(), script.invokeMethod("getAttributeProperty", new Object[] { DeviceCapability.NAME, "definition" }));
replacedertEquals(DeviceCapability.NAME, script.invokeMethod("getAttributeProperty", new Object[] { DeviceCapability.NAME, "capabilityName" }));
replacedertEquals(DeviceCapability.NAMESPACE, script.invokeMethod("getAttributeProperty", new Object[] { DeviceCapability.NAME, "namespace" }));
replacedertEquals(deviceCapability().getAttributes().values(), script.invokeMethod("getAttributeProperty", new Object[] { DeviceCapability.NAME, "attributes" }));
replacedertEquals(deviceCapability().getCommands().values(), script.invokeMethod("getAttributeProperty", new Object[] { DeviceCapability.NAME, "commands" }));
replacedertEquals(deviceCapability().getEvents().values(), script.invokeMethod("getAttributeProperty", new Object[] { DeviceCapability.NAME, "events" }));
}
@Test
public void testUnknownProperty() throws Exception {
try {
script.invokeMethod("setAttributeValue", new Object[] { DeviceCapability.NAME, "noSuchAttribute", "value" });
fail("Allowed a non-existent attribute to be set");
} catch (Exception e) {
// expected
e.printStackTrace(System.out);
}
}
}
17
Source : PersonHandlerHelper.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
/**
* Send the ValueChangeEvent to every place this given person belongs to
* @param personPlacereplacedocDao
* @param platformBus
* @param populationCacheMgr
* @param sourceAddress
* @param personId
* @param changes
* @return
*/
public boolean sendPersonValueChangesToPlaces(PersonPlacereplacedocDAO personPlacereplacedocDao, PlatformMessageBus platformBus, PlacePopulationCacheManager populationCacheMgr, Address sourceAddress, UUID personId, Map<String, Object> changes) {
Set<UUID> placeIds = personPlacereplacedocDao.findPlaceIdsByPerson(personId);
if (!CollectionUtils.isEmpty(placeIds)) {
placeIds.stream().forEach(placeId -> sendValueChangeEventForPlace(platformBus, populationCacheMgr, sourceAddress, changes, placeId.toString()));
return true;
} else {
return false;
}
}
17
Source : PairingDeviceResolver.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced PairingDeviceResolver implements ArgumentResolverFactory<PlatformMessage, MessageBody> {
private static final Type PairingDeviceWrapper = new TypeToken<PersistentModelWrapper<PairingDevice>>() {
}.getType();
private final PlatformMessageBus messageBus;
private final PairingDeviceDao pairingDeviceDao;
protected final PlacePopulationCacheManager populationCacheMgr;
@Inject
public PairingDeviceResolver(PlatformMessageBus messageBus, PairingDeviceDao pairingDeviceDao, PlacePopulationCacheManager populationCacheMgr) {
this.messageBus = messageBus;
this.pairingDeviceDao = pairingDeviceDao;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public Function<? super PlatformMessage, ?> getResolverForParameter(Method method, Type parameter, Annotation[] annotations) {
if (PairingDevice.clreplaced.equals(parameter)) {
return this::findPairingDevice;
}
if (PersistentModelWrapper.clreplaced.equals(TypeUtils.getRawType(parameter, null)) && TypeUtils.isreplacedignable(PairingDeviceWrapper, parameter)) {
return this::findPairingDeviceWrapper;
}
return null;
}
@Override
public Function<Object, MessageBody> getResolverForReturnType(Method method) {
return null;
}
public PairingDevice findPairingDevice(PlatformMessage message) {
Errors.replacedertPlaceMatches(message, (UUID) message.getDestination().getId());
PairingDevice device = pairingDeviceDao.findByAddress(message.getDestination());
Errors.replacedertFound(device, message.getDestination());
return device;
}
public PersistentModelWrapper<PairingDevice> findPairingDeviceWrapper(PlatformMessage message) {
PairingDevice device = findPairingDevice(message);
return new PersistentModelWrapper<PairingDevice>(messageBus, pairingDeviceDao, device.getPlaceId(), populationCacheMgr.getPopulationByPlaceId(device.getPlaceId()), device);
}
}
17
Source : CommandExecutor.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced CommandExecutor {
private static final Logger logger = LoggerFactory.getLogger(CommandExecutor.clreplaced);
private final ExecutorService executor;
private final VoiceConfig config;
private final HashedWheelTimer timeoutTimer;
private final PlatformBusClient busClient;
private final ResponseCompleter responseCompleter;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public CommandExecutor(PlatformMessageBus bus, @Named(VoiceConfig.NAME_EXECUTOR) ExecutorService executor, VoiceConfig config, @Named(VoiceConfig.NAME_TIMEOUT_TIMER) HashedWheelTimer timeoutTimer, ResponseCompleter responseCompleter, PlacePopulationCacheManager populationCacheMgr) {
this.executor = executor;
this.config = config;
this.timeoutTimer = timeoutTimer;
this.responseCompleter = responseCompleter;
this.populationCacheMgr = populationCacheMgr;
this.busClient = new PlatformBusClient(bus, executor, ImmutableSet.of(AddressMatchers.equals(Address.platformService(VoiceService.NAMESPACE))));
}
public ListenableFuture<Pair<Model, Optional<PlatformMessage>>> execute(Address addr, MessageBody body, VoiceContext context, boolean cheat, boolean updateModelOnCheat) {
PlatformMessage reqMsg = PlatformMessage.buildRequest(body, Address.platformService(VoiceService.NAMESPACE), addr).withPlaceId(context.getPlaceId()).withPopulation(populationCacheMgr.getPopulationByPlaceId(context.getPlaceId())).withCorrelationId(IrisUUID.randomUUID().toString()).withTimeToLive((int) config.getExecutionPerReqTimeoutMs()).create();
return execute(reqMsg, context, cheat, updateModelOnCheat);
}
private ListenableFuture<Pair<Model, Optional<PlatformMessage>>> execute(PlatformMessage reqMsg, VoiceContext context, boolean cheat, boolean updateModelOnCheat) {
SettableFuture<Pair<Model, Optional<PlatformMessage>>> future = SettableFuture.create();
Model m = context.getModelByAddress(reqMsg.getDestination());
final Model clone = new SimpleModel(m);
Map<String, Object> expected = new HashMap<>(reqMsg.getValue().getAttributes());
if (cheat) {
if (updateModelOnCheat) {
clone.update(expected);
}
} else if (!expected.isEmpty()) {
ResponseCorrelator correlator = new ResponseCorrelator(reqMsg.getCorrelationId(), reqMsg.getValue().getAttributes().keySet(), future);
responseCompleter.completeResponse(m.getAddress(), correlator);
}
final ListenableFuture<PlatformMessage> reqFuture = busClient.request(reqMsg);
Futures.addCallback(reqFuture, new RequestCallback(cheat, future, clone), executor);
timeoutTimer.newTimeout((timer) -> {
if (!future.isDone()) {
future.setException(new TimeoutException());
}
}, config.getExecutionPerReqTimeoutMs(), TimeUnit.MILLISECONDS);
return future;
}
private static clreplaced RequestCallback implements FutureCallback<PlatformMessage> {
private final boolean cheat;
private final SettableFuture<Pair<Model, Optional<PlatformMessage>>> future;
private final Model clone;
RequestCallback(boolean cheat, SettableFuture<Pair<Model, Optional<PlatformMessage>>> future, Model clone) {
this.cheat = cheat;
this.future = future;
this.clone = clone;
}
@Override
public void onSuccess(PlatformMessage result) {
if (cheat && !future.isDone()) {
logger.trace("completing via cheat");
future.set(new ImmutablePair<>(clone, Optional.of(result)));
}
}
@Override
public void onFailure(@NonNull Throwable t) {
if (!future.isDone()) {
future.setException(t);
}
}
}
}
17
Source : QuotaManager.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced QuotaManager {
private final VideoServiceConfig config;
private final VideoDao videoDao;
private final PlatformMessageBus messageBus;
private final LoadingCache<UUID, QuotaEntry> favoriteQuotaCache;
private final PlacePopulationCacheManager populationCacheMgr;
private final PlaceServiceLevelCache serviceLevelCache;
@Inject
public QuotaManager(VideoServiceConfig config, VideoDao videoDao, PlatformMessageBus messageBus, PlacePopulationCacheManager populationCacheMgr, PlaceServiceLevelCache serviceLevelCache) {
this.config = config;
this.videoDao = videoDao;
this.messageBus = messageBus;
this.populationCacheMgr = populationCacheMgr;
this.serviceLevelCache = serviceLevelCache;
this.favoriteQuotaCache = CacheBuilder.newBuilder().recordStats().expireAfterAccess(config.getQuotaCacheAccessExpirationTime(), TimeUnit.MILLISECONDS).expireAfterWrite(config.getQuotaCacheExpirationTime(), TimeUnit.MILLISECONDS).build(new CacheLoader<UUID, QuotaEntry>() {
@Override
public QuotaEntry load(UUID key) throws Exception {
long favoriteCount = videoDao.countByTag(key, VideoConstants.TAG_FAVORITE);
return new QuotaEntry((new Date()).getTime(), favoriteCount, Unit.Number);
}
});
}
public PlaceQuota getQuotaForPlace(UUID placeId, boolean favorite) {
if (!favorite) {
// No longer supported
return new PlaceQuota(0, System.currentTimeMillis(), ServiceLevel.isPremiumOrPromon(serviceLevelCache.getServiceLevel(placeId)) ? config.getVideoPremiumQuota() : config.getVideoBasicQuota(), Unit.Bytes);
} else {
QuotaEntry entry = favoriteQuotaCache.getUnchecked(placeId);
return new PlaceQuota(entry.used, entry.timestamp, ServiceLevel.isPremiumOrPromon(serviceLevelCache.getServiceLevel(placeId)) ? config.getVideoPremiumMaxFavorite() : config.getVideoBasicMaxFavorite(), Unit.Number);
}
}
public boolean updateQuotaIf(UUID placeId, long timestamp, long used, Unit unit, boolean favorite) {
QuotaEntry entry = new QuotaEntry(timestamp, used, unit);
if (favorite) {
return updateQuotaFor(placeId, favoriteQuotaCache, entry);
} else {
// no longer supported
return false;
}
}
private boolean updateQuotaFor(UUID placeId, LoadingCache<UUID, QuotaEntry> cache, QuotaEntry entry) {
for (int i = 0; i < 10; i++) {
QuotaEntry old = cache.getIfPresent(placeId);
if (old == null || old.timestamp > entry.timestamp) {
return false;
}
if (cache.asMap().replace(placeId, old, entry)) {
return true;
}
}
return false;
}
public void sendQuotaReportEvent(UUID placeId, long used, long usedTimestamp, Unit unit, boolean favorite) {
PlatformMessage message = VideoV2Util.createQuotaReportEvent(placeId, populationCacheMgr.getPopulationByPlaceId(placeId), used, usedTimestamp, unit, favorite);
messageBus.send(message);
}
public void invalidateQuotaCache() {
favoriteQuotaCache.invalidateAll();
}
public void invalidateQuotaCache(UUID placeId) {
if (placeId != null) {
favoriteQuotaCache.invalidate(placeId);
}
}
@Deprecated
public long decrementQuota(UUID placeId, long deleted) {
return 0l;
}
private static final clreplaced QuotaEntry {
private final long timestamp;
private final long used;
private final Unit unit;
QuotaEntry(long timestamp, long used, Unit unit) {
this.timestamp = timestamp;
this.used = used;
this.unit = unit;
}
}
}
17
Source : CachingSubsystemRegistry.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
/**
*/
@Singleton
public clreplaced CachingSubsystemRegistry implements SubsystemRegistry {
private static final Logger logger = LoggerFactory.getLogger(CachingSubsystemRegistry.clreplaced);
public static final Set<String> TRACKED_TYPES = ImmutableSet.<String>builder().add(AccountCapability.NAMESPACE).add(DeviceCapability.NAMESPACE).add(HubCapability.NAMESPACE).add(PairingDeviceCapability.NAMESPACE).add(PersonCapability.NAMESPACE).add(PlaceCapability.NAMESPACE).add(SchedulerCapability.NAMESPACE).add(// care listens to itself, may be other cases
SubsystemCapability.NAMESPACE).build();
private SubsystemFactory factory;
private PlaceDAO placeDao;
private ModelDao modelDao;
private final PlacePopulationCacheManager populationCacheMgr;
// it would be nice to use optional here, but we don't
// want negative caching
private final Cache<UUID, SubsystemExecutor> executors;
/**
*/
@Inject
public CachingSubsystemRegistry(SubsystemFactory factory, PlaceDAO placeDao, ModelDao modelDao, PlacePopulationCacheManager populationCacheMgr, SubsystemConfig config) {
this.factory = factory;
this.placeDao = placeDao;
this.modelDao = modelDao;
this.populationCacheMgr = populationCacheMgr;
CacheBuilder<Object, Object> bld = CacheBuilder.newBuilder();
if (config.getPlaceCacheConcurrencyLevel() > 0) {
bld = bld.concurrencyLevel(config.getPlaceCacheConcurrencyLevel());
}
if (config.getPlaceCacheExpireAccessMs() > 0) {
bld = bld.expireAfterAccess(config.getPlaceCacheExpireAccessMs(), TimeUnit.MILLISECONDS);
}
if (config.getPlaceCacheInitialCapacity() > 0) {
bld = bld.initialCapacity(config.getPlaceCacheInitialCapacity());
}
if (config.getPlaceCacheMaxSize() > 0) {
bld = bld.maximumSize(config.getPlaceCacheMaxSize());
}
if (config.isPlaceCacheSoftValues()) {
bld = bld.softValues();
}
this.executors = bld.recordStats().<UUID, SubsystemExecutor>removalListener((event) -> onRemoved(event.getValue())).build();
IrisMetricSet metrics = IrisMetrics.metrics("subsystems");
metrics.monitor("cache", executors);
}
/* (non-Javadoc)
* @see com.iris.platform.subsystem.SubsystemRegistry#loadByPlace(java.util.UUID)
*/
@Override
public Optional<SubsystemExecutor> loadByPlace(UUID placeId) {
if (placeId == null) {
return Optional.empty();
}
try {
SubsystemExecutor executor = executors.get(placeId, () -> doLoadByPlace(placeId));
return Optional.of(executor);
} catch (Exception e) {
logger.debug("Unable to load cache entry for placeId {}", placeId, e);
return Optional.empty();
}
}
// preplaceding in a place verifies the place exists
@Override
public Optional<SubsystemExecutor> loadByPlace(UUID placeId, UUID accountId) {
try {
if (placeId == null || accountId == null) {
return Optional.empty();
}
return Optional.of(executors.get(placeId, () -> doLoadByPlace(placeId, accountId)));
} catch (Exception e) {
logger.debug("Unable to load cache entry for place {}", placeId, e);
return Optional.empty();
}
}
/* (non-Javadoc)
* @see com.iris.platform.subsystem.SubsystemRegistry#removeByPlace(java.util.UUID)
*/
@Override
public void removeByPlace(UUID placeId) {
executors.invalidate(placeId);
}
/* (non-Javadoc)
* @see com.iris.platform.subsystem.SubsystemRegistry#clear()
*/
@Override
public void clear() {
executors.invalidateAll();
}
protected void onRemoved(SubsystemExecutor executor) {
if (executor == null) {
// soft reference was cleared
return;
}
logger.debug("Cache expired for executor at {}", executor.context().getPlaceId());
executor.stop();
}
protected SubsystemExecutor doLoadByPlace(UUID placeId) {
// ensure the place exists before loading the cache entry
UUID accountId = placeDao.getAccountById(placeId);
return doLoadByPlace(placeId, accountId);
}
protected SubsystemExecutor doLoadByPlace(UUID placeId, UUID accountId) {
if (placeId != null && accountId != null) {
PlaceContext rootContext = loadPlaceContext(placeId, populationCacheMgr.getPopulationByPlaceId(placeId), accountId);
if (rootContext == null) {
return null;
}
SubsystemExecutor executor = factory.createExecutor(rootContext);
executor.start();
return executor;
} else {
return null;
}
}
private PlaceContext loadPlaceContext(UUID placeId, String population, UUID accountId) {
Collection<Model> models = modelDao.loadModelsByPlace(placeId, TRACKED_TYPES);
PlatformSubsystemModelStore store = new PlatformSubsystemModelStore();
store.setTrackedTypes(TRACKED_TYPES);
store.addModels(models.stream().filter((m) -> m != null).map((m) -> SubsystemCapability.NAMESPACE.equals(m.getAttribute(Capability.ATTR_TYPE)) ? m : new SimpleModel(m)).collect(Collectors.toList()));
return new SimplePlaceContext(placeId, population, accountId, LoggerFactory.getLogger("subsystem." + placeId), store);
}
}
17
Source : PlatformSchedulerCapabilityDispatcher.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
clreplaced PlatformSchedulerCapabilityDispatcher extends BaseModelHandler implements SchedulerCapabilityDispatcher {
private static final Logger logger = LoggerFactory.getLogger(PlatformSchedulerCapabilityDispatcher.clreplaced);
private final SingleThreadDispatcher<AddressableEvent> dispatcher;
private final SchedulerRequestHandler handler;
private final PlatformMessageBus platformBus;
private final SchedulerModelDao schedulerDao;
private final EventSchedulerService schedulerService;
private final PlacePopulationCacheManager populationCacheMgr;
private ModelEnreplacedy scheduler;
private boolean delete = false;
public PlatformSchedulerCapabilityDispatcher(SchedulerContext context, PlatformMessageBus platformBus, SchedulerModelDao schedulerDao, EventSchedulerService schedulerService, DefinitionRegistry registry, PlacePopulationCacheManager populationCacheMgr) {
this.scheduler = context.getScheduler();
this.platformBus = platformBus;
this.schedulerDao = schedulerDao;
this.populationCacheMgr = populationCacheMgr;
this.schedulerService = schedulerService;
this.handler = SchedulerRequestHandler.fromContext(context);
this.dispatcher = new SingleThreadDispatcher<>((event) -> handleEvent(event), 100);
super.setDefinitionRegistry(registry);
}
@Override
public Model getScheduler() {
return scheduler;
}
@Override
public void onPlatformMessage(PlatformMessage message) {
dispatcher.dispatchOrQueue(new MessageReceivedEvent(message));
}
@Override
public void onScheduledEvent(ScheduledEvent event) {
dispatcher.dispatchOrQueue(event);
}
@Override
public void delete() {
Date nextFireTime = SchedulerModel.getNextFireTime(scheduler);
deleteScheduler();
commit(nextFireTime);
}
protected void handleEvent(AddressableEvent event) {
try (MdcContextReference context = MdcContext.captureMdcContext()) {
MDC.put(MdcContext.MDC_TARGET, scheduler.getAddress().getRepresentation());
MDC.put(MdcContext.MDC_PLACE, SchedulerModel.getPlaceId(scheduler));
Date nextFireTime = SchedulerModel.getNextFireTime(scheduler);
if (event instanceof ScheduledEvent) {
handleScheduledEvent((ScheduledEvent) event);
} else if (event instanceof MessageReceivedEvent) {
handleRequest(((MessageReceivedEvent) event).getMessage());
}
commit(nextFireTime);
} catch (Exception e) {
logger.warn("Error handling request", e);
}
}
/* (non-Javadoc)
* @see com.iris.messages.handler.BaseModelHandler#setAttributes(com.iris.messages.model.Model, java.util.Map)
*/
@Override
protected MessageBody setAttributes(Model model, Map<String, Object> attributes) {
try {
return super.setAttributes(model, attributes);
} finally {
handler.updated();
}
}
@Override
protected void setAttribute(Model model, String name, Object value) throws ErrorEventException {
super.setAttribute(model, name, value);
if (name.startsWith(ScheduleCapability.ATTR_ENABLED) && Boolean.TRUE.equals(value)) {
String enabledInstanceId = NamespacedKey.parse(name).getInstance();
String group = ScheduleModel.getGroup(enabledInstanceId, model, "");
for (String instanceId : model.getInstances().keySet()) {
if (enabledInstanceId.equals(instanceId)) {
continue;
}
if (!group.equals(ScheduleModel.getGroup(instanceId, model))) {
continue;
}
ScheduleModel.setEnabled(instanceId, model, false);
}
}
}
private void commit(Date previousFireTime) {
String placeIdStr = SchedulerModel.getPlaceId(scheduler);
UUID placeId = UUID.fromString(placeIdStr);
String command;
Map<String, Object> attributes;
if (delete) {
command = Capability.EVENT_DELETED;
attributes = scheduler.toMap();
schedulerDao.delete(scheduler);
schedulerService.cancelEvent(placeId, scheduler.getAddress(), previousFireTime);
} else if (scheduler.isPersisted() && !scheduler.getCreated().equals(scheduler.getModified())) {
if (!scheduler.isDirty()) {
return;
}
command = Capability.EVENT_VALUE_CHANGE;
attributes = scheduler.getDirtyAttributes();
scheduler = schedulerDao.save(scheduler);
Date nextFireTime = SchedulerModel.getNextFireTime(scheduler);
if (nextFireTime == null) {
schedulerService.cancelEvent(placeId, scheduler.getAddress(), previousFireTime);
} else if (previousFireTime == null) {
schedulerService.fireEventAt(placeId, scheduler.getAddress(), nextFireTime);
} else if (previousFireTime != null) {
schedulerService.rescheduleEventAt(placeId, scheduler.getAddress(), previousFireTime, nextFireTime);
}
} else {
scheduler = schedulerDao.save(scheduler);
command = Capability.EVENT_ADDED;
attributes = scheduler.toMap();
Date nextFireTime = SchedulerModel.getNextFireTime(scheduler);
if (nextFireTime != null) {
schedulerService.fireEventAt(placeId, scheduler.getAddress(), nextFireTime);
}
}
if (attributes.isEmpty()) {
return;
}
MessageBody event = MessageBody.buildMessage(command, attributes);
PlatformMessage message = PlatformMessage.builder().from(scheduler.getAddress()).withPayload(event).withPlaceId(placeIdStr).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeId)).broadcast().create();
platformBus.send(message);
scheduler.clearDirty();
}
private void handleScheduledEvent(ScheduledEvent event) {
Date nextFireTime = SchedulerModel.getNextFireTime(scheduler, null);
if (nextFireTime == null) {
logger.debug("Received scheduled event for disabled schedule: [{}]", event);
return;
}
if (nextFireTime.getTime() > event.getScheduledTimestamp()) {
logger.debug("Ignoring early scheduled event, likely failed to cancel previous event: [{}]", event);
return;
}
String scheduleId = SchedulerModel.getNextFireSchedule(scheduler);
String commandId = ScheduleModel.getNextFireCommand(scheduleId, scheduler, null);
if (commandId == null) {
logger.debug("Corrupt config, can't determine command to run, exiting");
// attempt to re-calculate next fire time
handler.updated();
return;
}
// advance current time by at least 1 second
Optional<MessageBody> request = handler.fire(commandId, new Date(event.getScheduledTimestamp() + 1000));
if (!request.isPresent()) {
logger.debug("No requests to send for command [{}]", commandId);
return;
}
sendRequest(request.get());
}
private void handleRequest(PlatformMessage message) {
if (message.getDestination().isBroadcast()) {
handleUpdate(message);
} else {
platformBus.invokeAndSendResponse(message, () -> doHandleRequest(message, message.getValue()));
}
}
private void handleUpdate(PlatformMessage message) {
Date nextFireTime = SchedulerModel.getNextFireTime(scheduler);
if (Capability.EVENT_VALUE_CHANGE.equals(message.getMessageType())) {
MessageBody value = message.getValue();
String tzId = PlaceCapability.getTzId(value);
if (!StringUtils.isEmpty(tzId)) {
TimeZone tz = TimeZone.getTimeZone(tzId);
logger.info("Updating timezone for place [{}], requested: [{}] result: [{}]", message.getPlaceId(), tzId, tz.getID());
handler.setTimeZone(tz);
}
Double longitude = PlaceCapability.getAddrLongitude(value);
Double lareplacedude = PlaceCapability.getAddrLareplacedude(value);
if (longitude != null && lareplacedude != null) {
handler.setLocation(GeoLocation.fromCoordinates(lareplacedude, longitude));
}
}
commit(nextFireTime);
}
private MessageBody doHandleRequest(PlatformMessage message, MessageBody request) {
boolean isStatic = Address.ZERO_UUID.equals(message.getDestination().getId());
if (isStatic) {
switch(message.getMessageType()) {
case SchedulerService.ScheduleCommandsRequest.NAME:
List<String> commandIds = scheduleCommands(request);
return SchedulerService.ScheduleCommandsResponse.builder().withSchedulerAddress(scheduler.getAddress().getRepresentation()).withCommandIds(commandIds).build();
case SchedulerService.ScheduleWeeklyCommandRequest.NAME:
TimeOfDayCommand command = scheduleWeeklyCommand(request);
return SchedulerService.ScheduleWeeklyCommandResponse.builder().withCommandId(command.getId()).withSchedulerAddress(scheduler.getAddress().getRepresentation()).build();
case SchedulerService.FireCommandRequest.NAME:
fireCommand(request);
return SchedulerService.FireCommandResponse.instance();
case SchedulerService.UpdateWeeklyCommandRequest.NAME:
updateWeeklyCommand(request);
return SchedulerService.UpdateWeeklyCommandResponse.instance();
case SchedulerService.DeleteCommandRequest.NAME:
deleteCommand(request);
return SchedulerService.DeleteCommandResponse.instance();
}
return Errors.unsupportedMessageType(message.getMessageType());
}
NamespacedKey key = NamespacedKey.parse(message.getMessageType());
if (!key.isInstanced()) {
switch(key.getNamedRepresentation()) {
case Capability.CMD_GET_ATTRIBUTES:
Set<String> names = Capability.GetAttributesRequest.getNames(message.getValue());
return getAttributes(scheduler, names);
case Capability.CMD_SET_ATTRIBUTES:
Map<String, Object> attributes = message.getValue().getAttributes();
return setAttributes(scheduler, attributes);
case Capability.CMD_ADD_TAGS:
Set<String> tagsToAdd = Capability.AddTagsRequest.getTags(message.getValue());
removeTags(scheduler, tagsToAdd);
return Capability.AddTagsResponse.instance();
case Capability.CMD_REMOVE_TAGS:
Set<String> tagsToRemove = Capability.RemoveTagsRequest.getTags(message.getValue());
removeTags(scheduler, tagsToRemove);
return Capability.RemoveTagsResponse.instance();
case SchedulerCapability.DeleteRequest.NAME:
deleteScheduler();
return SchedulerCapability.DeleteResponse.instance();
case SchedulerCapability.AddWeeklyScheduleRequest.NAME:
addWeeklySchedule(request);
return SchedulerCapability.AddWeeklyScheduleResponse.instance();
case SchedulerCapability.FireCommandRequest.NAME:
fireCommand(request);
return SchedulerCapability.FireCommandResponse.instance();
case SchedulerCapability.RecalculateScheduleRequest.NAME:
handler.updated();
return SchedulerCapability.RecalculateScheduleResponse.instance();
}
return Errors.unsupportedMessageType(message.getMessageType());
} else {
String scheduleId = key.getInstance();
switch(key.getNamedRepresentation()) {
case ScheduleCapability.DeleteRequest.NAME:
deleteSchedule(scheduleId);
return ScheduleCapability.DeleteResponse.instance();
case ScheduleCapability.DeleteCommandRequest.NAME:
deleteCommand(scheduleId, request);
return ScheduleCapability.DeleteCommandResponse.instance();
case WeeklyScheduleCapability.ScheduleWeeklyCommandRequest.NAME:
TimeOfDayCommand command = scheduleWeeklyCommand(scheduleId, request);
return WeeklyScheduleCapability.ScheduleWeeklyCommandResponse.builder().withCommandId(command.getId()).build();
case WeeklyScheduleCapability.UpdateWeeklyCommandRequest.NAME:
updateWeeklyCommand(scheduleId, request);
return WeeklyScheduleCapability.UpdateWeeklyCommandResponse.instance();
}
return Errors.unsupportedMessageType(message.getMessageType());
}
}
private void addWeeklySchedule(MessageBody request) {
String scheduleId = SchedulerCapability.AddWeeklyScheduleRequest.getId(request);
Errors.replacedertRequiredParam(scheduleId, SchedulerCapability.AddWeeklyScheduleRequest.ATTR_ID);
String group = SchedulerCapability.AddWeeklyScheduleRequest.getGroup(request);
handler.addWeeklySchedule(scheduleId, group);
}
private void deleteScheduler() {
delete = true;
}
private void deleteSchedule(String scheduleId) {
handler.deleteSchedule(scheduleId);
}
private void deleteCommand(MessageBody request) {
String scheduleId = SchedulerService.DeleteCommandRequest.getSchedule(request);
String commandId = ScheduleCapability.DeleteCommandRequest.getCommandId(request);
Errors.replacedertRequiredParam(scheduleId, SchedulerService.DeleteCommandRequest.ATTR_SCHEDULE);
Errors.replacedertRequiredParam(commandId, SchedulerService.DeleteCommandRequest.ATTR_COMMANDID);
handler.deleteCommand(scheduleId, commandId);
}
private void deleteCommand(String scheduleId, MessageBody request) {
String commandId = ScheduleCapability.DeleteCommandRequest.getCommandId(request);
Errors.replacedertRequiredParam(commandId, ScheduleCapability.DeleteCommandRequest.ATTR_COMMANDID);
handler.deleteCommand(scheduleId, commandId);
}
private List<String> scheduleCommands(MessageBody request) {
String group = ScheduleCommandsRequest.getGroup(request);
if (StringUtils.isEmpty(group)) {
group = null;
}
List<Map<String, Object>> requestCommands = ScheduleCommandsRequest.getCommands(request);
List<TimeOfDayScheduledCommand> translated = new ArrayList<>(requestCommands.size());
for (Map<String, Object> requestCommand : requestCommands) {
TimeOfDayScheduledCommand command = TimeOfDayScheduledCommand.fromMap(requestCommand);
command.validate();
translated.add(command);
}
return handler.scheduleCommands(Optional.fromNullable(group), translated);
}
private void fireCommand(MessageBody request) {
String commandId = FireCommandRequest.getCommandId(request);
Errors.replacedertRequiredParam(commandId, FireCommandRequest.ATTR_COMMANDID);
MessageBody body = handler.fire(commandId, new Date()).orNull();
if (body == null) {
throw new ErrorEventException(Errors.invalidParam(FireCommandRequest.ATTR_COMMANDID));
}
sendRequest(body);
}
private TimeOfDayCommand scheduleWeeklyCommand(MessageBody request) {
String scheduleId = ScheduleWeeklyCommandRequest.getSchedule(request);
Errors.replacedertRequiredParam(scheduleId, ScheduleWeeklyCommandRequest.ATTR_SCHEDULE);
TimeOfDayScheduledCommand command = TimeOfDayScheduledCommand.fromMap(request.getAttributes());
command.setScheduleId(scheduleId);
command.validate();
return handler.scheduleWeeklyCommand(scheduleId, command);
}
private TimeOfDayCommand scheduleWeeklyCommand(String scheduleId, MessageBody request) {
TimeOfDayScheduledCommand command = TimeOfDayScheduledCommand.fromMap(request.getAttributes());
command.setScheduleId(scheduleId);
command.validate();
return handler.scheduleWeeklyCommand(scheduleId, command);
}
private void updateWeeklyCommand(MessageBody request) {
String scheduleId = UpdateWeeklyCommandRequest.getSchedule(request);
String commandId = UpdateWeeklyCommandRequest.getCommandId(request);
Errors.replacedertRequiredParam(scheduleId, UpdateWeeklyCommandRequest.ATTR_SCHEDULE);
Errors.replacedertRequiredParam(commandId, UpdateWeeklyCommandRequest.ATTR_COMMANDID);
TimeOfDayScheduledCommand command = TimeOfDayScheduledCommand.fromMap(request.getAttributes());
command.setId(commandId);
command.setScheduleId(scheduleId);
// don't validate on update
handler.updateWeeklyCommand(scheduleId, command);
}
private void updateWeeklyCommand(String scheduleId, MessageBody request) {
String commandId = WeeklyScheduleCapability.UpdateWeeklyCommandRequest.getCommandId(request);
Errors.replacedertRequiredParam(commandId, WeeklyScheduleCapability.UpdateWeeklyCommandRequest.ATTR_COMMANDID);
TimeOfDayScheduledCommand command = TimeOfDayScheduledCommand.fromMap(request.getAttributes());
command.setId(commandId);
command.setScheduleId(scheduleId);
// don't validate on an update, we need to merge with the existing command first
handler.updateWeeklyCommand(scheduleId, command);
}
// TODO retries & timeouts
private void sendRequest(MessageBody request) {
Address targetAddress = Address.fromString(SchedulerModel.getTarget(scheduler));
String placeIdStr = SchedulerModel.getPlaceId(scheduler);
PlatformMessage message = PlatformMessage.request(targetAddress).from(scheduler.getAddress()).withPlaceId(placeIdStr).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeIdStr)).withActor(scheduler.getAddress()).withPayload(request).create();
platformBus.send(message);
}
}
17
Source : AbstractRegisterHubHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
public abstract clreplaced AbstractRegisterHubHandler implements ContextualRequestMessageHandler<Place> {
private static final Logger logger = LoggerFactory.getLogger(AbstractRegisterHubHandler.clreplaced);
protected final PlatformMessageBus bus;
protected final HubDAO hubDao;
protected final HubRegistrationDAO hubRegistrationDao;
protected final PlacePopulationCacheManager populationCacheMgr;
public AbstractRegisterHubHandler(PlatformMessageBus bus, HubDAO hubDao, HubRegistrationDAO hubRegistrationDao, PlacePopulationCacheManager populationCacheMgr) {
this.bus = bus;
this.hubDao = hubDao;
this.hubRegistrationDao = hubRegistrationDao;
this.populationCacheMgr = populationCacheMgr;
}
public abstract String getMessageType();
public abstract MessageBody handleRequest(Place context, PlatformMessage msg);
protected void emitAddedEvent(Model hub, String correlationId) {
MessageBody body = MessageBody.buildMessage(Capability.EVENT_ADDED, hub.toMap());
String placeId = HubModel.getPlace(hub);
PlatformMessage added = PlatformMessage.buildBroadcast(body, hub.getAddress()).withCorrelationId(correlationId).withPlaceId(placeId).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeId)).create();
bus.send(added);
}
protected void sendHubRegistered(String hubId, UUID accountId, UUID placeId, String population) {
Address hubAddress = Address.hubService(hubId, "hub");
MessageBody valueChange = MessageBody.buildMessage(Capability.EVENT_VALUE_CHANGE, ImmutableMap.of(HubCapability.ATTR_ACCOUNT, String.valueOf(accountId), HubCapability.ATTR_PLACE, String.valueOf(placeId), HubCapability.ATTR_REGISTRATIONSTATE, HubCapability.REGISTRATIONSTATE_REGISTERED));
// don't populate the placeId header here, that way anything listening on an old parreplacedion
// knows what was happening
bus.send(PlatformMessage.createBroadcast(valueChange, hubAddress));
Map<String, Object> attrs = new HashMap<>();
attrs.put(HubCapability.ATTR_ACCOUNT, String.valueOf(accountId));
attrs.put(HubCapability.ATTR_PLACE, String.valueOf(placeId));
bus.send(PlatformMessage.buildMessage(MessageBody.buildMessage(MessageConstants.MSG_HUB_REGISTERED_REQUEST, attrs), Address.platformService(PlatformConstants.SERVICE_HUB), hubAddress).withPlaceId(placeId).withPopulation(population).create());
}
// TODO - I can update the hub_registration here instead of mothership listening for registered messages. But then HubRegistrationRegistry will have obsolete cache
// Maybe I should use a short lived cache like Cache<Serializable, HubRegistration> that expires after 20 min?
protected void updateHubRegistrationIfNecessary(Hub hub) {
if (HubCapability.REGISTRATIONSTATE_REGISTERED.equals(hub.getRegistrationState())) {
HubRegistration curHubReg = hubRegistrationDao.findById(hub.getId());
if (curHubReg != null) {
curHubReg.setState(RegistrationState.REGISTERED);
hubRegistrationDao.save(curHubReg);
}
}
}
protected void sendHubKitMessage(String hubId, UUID placeId, List<Map<String, Object>> devices, String type, String population) {
PlatformMessage setKitMessage = PlatformMessage.buildMessage(HubKitCapability.SetKitRequest.builder().withDevices(devices).withType(type).build(), Address.platformService(PlatformConstants.SERVICE_HUB), Address.hubService(hubId, HubCapability.NAMESPACE)).withPlaceId(placeId).withPopulation(population).create();
bus.send(setKitMessage);
}
protected void sendCreatePairingDevice(Map<String, Object> attributes, Address address, String productId, UUID placeId, String hubId, String population) {
PlatformMessage added = PlatformMessage.broadcast().from(address).withPlaceId(placeId).withPopulation(population).withPayload(MessageBody.buildMessage(Capability.EVENT_ADDED, attributes)).create();
bus.send(added);
}
}
17
Source : PersonDeleter.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced PersonDeleter {
private final AccountDAO accountDao;
private final PersonDAO personDao;
private final PlaceDAO placeDao;
private final AuthorizationGrantDAO grantDao;
private final PreferencesDAO preferencesDao;
private final PlatformMessageBus bus;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public PersonDeleter(AccountDAO accountDao, PersonDAO personDao, PlaceDAO placeDao, AuthorizationGrantDAO grantDao, PreferencesDAO preferencesDao, PlatformMessageBus bus, PlacePopulationCacheManager populationCacheMgr) {
this.accountDao = accountDao;
this.personDao = personDao;
this.placeDao = placeDao;
this.grantDao = grantDao;
this.preferencesDao = preferencesDao;
this.bus = bus;
this.populationCacheMgr = populationCacheMgr;
}
public void removePersonFromPlace(UUID placeId, Person person, Address eventActor, boolean sendNotification) {
Place p = placeDao.findById(placeId);
if (p == null) {
return;
}
removePersonFromPlace(p, person, eventActor, sendNotification);
}
public void removePersonFromPlace(Place place, UUID personId, Address eventActor, boolean sendNotification) {
Person p = personDao.findById(personId);
if (p == null) {
return;
}
removePersonFromPlace(place, p, eventActor, sendNotification);
}
public void removePersonFromPlace(Place place, Person person, Address eventActor, boolean sendNotification) {
Account account = accountDao.findById(place.getAccount());
removePersonFromPlace(account, place, person, eventActor, sendNotification);
}
public void removePersonFromPlace(Account account, Place place, Person person, Address eventActor, boolean sendNotification) {
// check for account null in the case that the account has been deleted concurrent to removing
// all of its dependencies or is a login that has no billable account
if (account != null && Objects.equal(account.getOwner(), person.getId())) {
throw new ErrorEventException("account.owner.deletion", "The account owner cannot be deleted without closing the account.");
}
List<AuthorizationGrant> grants = grantDao.findForEnreplacedy(person.getId());
if (grants.stream().noneMatch((g) -> {
return g.getPlaceId().equals(place.getId());
})) {
throw new ErrorEventException(Errors.CODE_NOT_FOUND, "person " + person.getId() + " not found at " + place.getId());
}
preferencesDao.delete(person.getId(), place.getId());
// check if this is the final place the person is removed from. - 1 because grants is prior
// to removal. because hobbits can only be at one place this covers both guests and hobbits
if (grants.size() - 1 == 0) {
grantDao.removeGrantsForEnreplacedy(person.getId());
personDao.delete(person);
// TODO: ITWO-5930: Send email that their login has been removed if person.hasLogin() == true
emitDeletedEvent(person, place.getId(), place.getPopulation(), true, eventActor);
if (sendNotification) {
sendNotification(person, place.getId(), place.getPopulation(), account, eventActor);
}
return;
} else {
// This is not the last place for this person
grantDao.removeGrant(person.getId(), place.getId());
clearPinForPlace(place.getId(), person, grants);
if (sendNotification) {
sendNotification(person, place.getId(), place.getPopulation(), account, eventActor);
}
emitAuthorizationRemoved(person, place.getId(), place.getPopulation());
emitDeletedEvent(person, place.getId(), place.getPopulation(), false, eventActor);
}
}
private void sendNotification(Person context, UUID placeId, String population, Account account, Address eventActor) {
Person actor = null;
if (eventActor != null) {
actor = InvitationHandlerHelper.getActorFromAddress(eventActor, personDao);
}
boolean personRemovedSelf = false;
if (actor != null && Objects.equal(actor.getId(), context.getId())) {
personRemovedSelf = true;
}
if (personRemovedSelf) {
EmailRecipient recipient = new EmailRecipient();
recipient.setEmail(context.getEmail());
recipient.setFirstName(context.getFirstName());
recipient.setLastName(context.getLastName());
Notifications.sendEmailNotification(bus, recipient, placeId.toString(), population, Notifications.FullAccessPersonRemoved.KEY, ImmutableMap.<String, String>of(), Address.platformService(PlatformConstants.SERVICE_PLACES));
} else if (actor != null && placeId != null) {
Notifications.sendEmailNotification(bus, actor.getId().toString(), placeId.toString(), population, Notifications.PersonRemovedByOther.KEY, ImmutableMap.<String, String>of(Notifications.PersonRemovedByOther.PARAM_REMOVED_FIRSTNAME, Notifications.ensureNotNull(context.getFirstName()), Notifications.PersonRemovedByOther.PARAM_REMOVED_LASTNAME, Notifications.ensureNotNull(context.getLastName())), Address.platformService(PlatformConstants.SERVICE_PLACES));
}
if (account != null && (actor != null && !Objects.equal(actor.getId(), account.getOwner()))) {
// send notification to account owner
if (personRemovedSelf) {
Notifications.sendEmailNotification(bus, account.getOwner().toString(), placeId.toString(), population, Notifications.PersonLeft.KEY, ImmutableMap.<String, String>of(Notifications.PersonLeft.PARAM_SECONDARY_FIRSTNAME, Notifications.ensureNotNull(context.getFirstName()), Notifications.PersonLeft.PARAM_SECONDARY_LASTNAME, Notifications.ensureNotNull(context.getLastName())), Address.platformService(PlatformConstants.SERVICE_PLACES));
} else {
Notifications.sendEmailNotification(bus, account.getOwner().toString(), placeId.toString(), population, Notifications.PersonRemovedByOtherNotifyOwner.KEY, ImmutableMap.<String, String>of(Notifications.PersonRemovedByOtherNotifyOwner.PARAM_REMOVED_FIRSTNAME, Notifications.ensureNotNull(context.getFirstName()), Notifications.PersonRemovedByOtherNotifyOwner.PARAM_REMOVED_LASTNAME, Notifications.ensureNotNull(context.getLastName()), Notifications.PersonRemovedByOtherNotifyOwner.PARAM_ACTOR_FIRSTNAME, Notifications.ensureNotNull(actor.getFirstName()), Notifications.PersonRemovedByOtherNotifyOwner.PARAM_ACTOR_LASTNAME, Notifications.ensureNotNull(actor.getLastName())), Address.platformService(PlatformConstants.SERVICE_PLACES));
}
}
}
public void clearPinForPlace(UUID placeId, Person person, List<AuthorizationGrant> grants) {
if (person == null) {
return;
}
if (person.hasPinAtPlace(placeId)) {
Person updatedPerson = personDao.deletePinAtPlace(person, placeId);
MessageBody body = MessageBody.buildMessage(Capability.EVENT_VALUE_CHANGE, ImmutableMap.of(PersonCapability.ATTR_PLACESWITHPIN, updatedPerson.getPlacesWithPin()));
grants.forEach((g) -> {
PlatformMessage evt = PlatformMessage.buildBroadcast(body, Address.fromString(updatedPerson.getAddress())).withPlaceId(g.getPlaceId()).withPopulation(populationCacheMgr.getPopulationByPlaceId(g.getPlaceId())).create();
bus.send(evt);
});
}
}
public void clearPinForPlace(UUID placeId, UUID personId) {
clearPinForPlace(placeId, personDao.findById(personId), grantDao.findForEnreplacedy(personId));
}
public void clearPinForPlace(UUID placeId, Person person) {
clearPinForPlace(placeId, person, grantDao.findForEnreplacedy(person.getId()));
}
private void emitAuthorizationRemoved(Person person, UUID placeId, String population) {
MessageBody body = PersonCapability.AuthorizationRemovedEvent.builder().withPlaceId(placeId.toString()).build();
PlatformMessage evt = PlatformMessage.buildBroadcast(body, Address.fromString(person.getAddress())).withPlaceId(placeId).withPopulation(population).create();
bus.send(evt);
}
private void emitDeletedEvent(Person person, UUID placeId, String population, boolean bootSession, Address actor) {
MessageBody body = MessageBody.buildMessage(Capability.EVENT_DELETED, ImmutableMap.of("bootSession", bootSession, PersonCapability.ATTR_HASLOGIN, person.getHasLogin(), PersonCapability.ATTR_OWNER, person.getOwner(), PersonCapability.ATTR_FIRSTNAME, Notifications.ensureNotNull(person.getFirstName()), PersonCapability.ATTR_LASTNAME, Notifications.ensureNotNull(person.getLastName())));
PlatformMessage evt = PlatformMessage.buildBroadcast(body, Address.fromString(person.getAddress())).withPlaceId(placeId).withPopulation(population).withActor(actor).create();
bus.send(evt);
}
}
17
Source : DeleteLoginHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced DeleteLoginHandler implements ContextualRequestMessageHandler<Person> {
private final PersonDAO personDao;
private final AuthorizationGrantDAO authGrantDao;
private final PreferencesDAO preferencesDao;
private final PlatformMessageBus bus;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public DeleteLoginHandler(PersonDAO personDao, AuthorizationGrantDAO authGrantDao, PreferencesDAO preferencesDao, PlatformMessageBus bus, PlacePopulationCacheManager populationCacheMgr) {
this.personDao = personDao;
this.authGrantDao = authGrantDao;
this.preferencesDao = preferencesDao;
this.bus = bus;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public String getMessageType() {
return PersonCapability.DeleteLoginRequest.NAME;
}
@Override
public MessageBody handleRequest(Person context, PlatformMessage msg) {
List<AuthorizationGrant> grants = authGrantDao.findForEnreplacedy(context.getId());
validate(context, grants, msg.getActor());
preferencesDao.deleteForPerson(context.getId());
authGrantDao.removeGrantsForEnreplacedy(context.getId());
personDao.delete(context);
emitDeleted(context, grants);
return PersonCapability.DeleteLoginResponse.instance();
}
private void emitDeleted(Person person, List<AuthorizationGrant> grants) {
MessageBody body = MessageBody.buildMessage(Capability.EVENT_DELETED, ImmutableMap.of("bootSession", true));
Address addr = Address.fromString(person.getAddress());
grants.forEach((g) -> {
PlatformMessage evt = PlatformMessage.buildBroadcast(body, addr).withPlaceId(g.getPlaceId()).withPopulation(populationCacheMgr.getPopulationByPlaceId(g.getPlaceId())).create();
bus.send(evt);
});
}
private void validate(Person context, List<AuthorizationGrant> grants, Address actor) {
if (!context.getHasLogin()) {
throw new ErrorEventException(Errors.invalidRequest("person does not have a login"));
}
if (grants.stream().anyMatch((g) -> {
return g.isAccountOwner();
})) {
throw new ErrorEventException("account.owner.deletion", "The account owner cannot be deleted without closing the account.");
}
if (!Objects.equal(context.getAddress(), actor.getRepresentation())) {
throw new ErrorEventException(Errors.invalidRequest("a login may only be deleted by themselves"));
}
}
}
17
Source : VerifyEmailRESTHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
@HttpPost("/" + PersonCapability.NAMESPACE + "/VerifyEmail")
public clreplaced VerifyEmailRESTHandler extends RESTHandler {
private static final Logger logger = LoggerFactory.getLogger(VerifyEmailRESTHandler.clreplaced);
private final PersonDAO personDao;
private final PlatformMessageBus platformBus;
private final PersonPlacereplacedocDAO personPlacereplacedocDao;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public VerifyEmailRESTHandler(SessionAuth auth, BridgeMetrics metrics, PersonDAO personDao, PersonPlacereplacedocDAO personPlacereplacedocDao, PlatformMessageBus platformBus, RESTHandlerConfig restHandlerConfig, PlacePopulationCacheManager populationCacheMgr) {
super(auth, new HttpSender(VerifyEmailRESTHandler.clreplaced, metrics), restHandlerConfig);
this.personDao = personDao;
this.platformBus = platformBus;
this.personPlacereplacedocDao = personPlacereplacedocDao;
this.populationCacheMgr = populationCacheMgr;
}
@Override
protected MessageBody doHandle(ClientMessage request) throws Exception {
// ensure person exists
String destinationStr = request.getDestination();
Person curPerson = loadPerson(destinationStr);
if (curPerson == null) {
throw new ErrorEventException(Errors.CODE_UNSUPPORTED_DESTINATION, "person [" + destinationStr + "] is not found. ");
}
// verify token in the request matches what is in the Person enreplacedy
MessageBody msgBody = request.getPayload();
String curToken = PersonCapability.VerifyEmailRequest.getToken(msgBody);
if (StringUtils.isBlank(curToken) || !curToken.equals(curPerson.getEmailVerificationToken())) {
throw new ErrorEventException(PersonCapability.VerifyEmailResponse.CODE_TOKEN_INVALID, "The token does not match the current email address.");
}
// update emailVerified field and send value change event for each place this person belongs to.
if (curPerson.getEmailVerified() == null) {
curPerson.setEmailVerified(new Date());
personDao.update(curPerson);
if (PersonHandlerHelper.getInstance().sendPersonValueChangesToPlaces(personPlacereplacedocDao, platformBus, populationCacheMgr, Address.fromString(request.getDestination()), curPerson.getId(), ImmutableMap.<String, Object>of(PersonCapability.ATTR_EMAILVERIFIED, Boolean.TRUE))) {
// ok
} else {
logger.warn("This should not happen, but person [{}] has no places replacedociated with it. Possibly index out of sync", curPerson.getId());
}
}
return PersonCapability.VerifyEmailResponse.instance();
}
private Person loadPerson(String destination) {
Address addr = Address.fromString(destination);
if (addr == null) {
return null;
}
return personDao.findById((UUID) addr.getId());
}
}
17
Source : SmartHomeSkillV3Handler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced SmartHomeSkillV3Handler implements SmartHomeSkillHandler {
private static final Logger logger = LoggerFactory.getLogger(SmartHomeSkillV3Handler.clreplaced);
private final ShsConfig config;
private final PlatformBusClient busClient;
private final ExecutorService executor;
private final VoiceBridgeMetrics metrics;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public SmartHomeSkillV3Handler(ShsConfig config, PlatformMessageBus bus, @Named(VoiceBridgeConfig.NAME_EXECUTOR) ExecutorService executor, VoiceBridgeMetrics metrics, PlacePopulationCacheManager populationCacheMgr) {
this.config = config;
this.executor = executor;
this.busClient = new PlatformBusClient(bus, executor, ImmutableSet.of(AddressMatchers.equals(AlexaUtil.ADDRESS_BRIDGE)));
this.metrics = metrics;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public boolean supports(AlexaMessage message) {
return message.getHeader().isV3();
}
@Override
public ListenableFuture<AlexaMessage> handle(AlexaMessage message, UUID placeId) {
long startTime = System.nanoTime();
Txfm txfm = Txfm.transformerFor(message);
PlatformMessage platformMessage = txfm.txfmRequest(message, placeId, populationCacheMgr.getPopulationByPlaceId(placeId), (int) config.getRequestTimeoutMs());
logger.debug("[{}] transformed to platform message [{}]", message, platformMessage);
return Futures.transformAsync(busClient.request(platformMessage), (AsyncFunction<PlatformMessage, AlexaMessage>) input -> {
metrics.timeServiceSuccess(platformMessage.getMessageType(), startTime);
return Futures.immediateFuture(txfm.transformResponse(input, message.getHeader().getCorrelationToken()));
}, executor);
}
@Override
public AlexaMessage transformException(AlexaMessage m, Throwable e) {
logger.warn("an exception occured handling {}", m, e);
MessageBody err = AlexaErrors.INTERNAL_ERROR;
Throwable cause = e;
if (e instanceof ExecutionException) {
cause = e.getCause();
}
if (cause instanceof AlexaException) {
err = ((AlexaException) cause).getErrorMessage();
}
Map<String, Object> payload = AlexaService.AlexaErrorEvent.getPayload(err);
String type = AlexaService.AlexaErrorEvent.getType(err);
Header h = Header.v3(m.getHeader().getMessageId(), AlexaInterfaces.RESPONSE_ERROR, errNamespace(type), m.getHeader().getCorrelationToken());
ImmutableMap.Builder<String, Object> payloadBuilder = ImmutableMap.<String, Object>builder().put("type", type).put("message", AlexaService.AlexaErrorEvent.getMessage(err));
if (payload != null) {
payloadBuilder.putAll(payload);
}
return new AlexaMessage(h, payloadBuilder.build());
}
private String errNamespace(String type) {
switch(type) {
case AlexaErrors.TYPE_THERMOSTAT_IS_OFF:
case AlexaErrors.TYPE_REQUESTED_SETPOINTS_TOO_CLOSE:
return AlexaInterfaces.ThermostatController.NAMESPACE;
default:
return AlexaInterfaces.RESPONSE_NAMESPACE;
}
}
@Override
public Optional<String> extractOAuthToken(AlexaMessage message) {
Txfm txfm = Txfm.transformerFor(message);
return txfm.extractRequestOauthToken(message);
}
}
17
Source : SmartHomeSkillV2Handler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced SmartHomeSkillV2Handler implements SmartHomeSkillHandler {
private static final Logger logger = LoggerFactory.getLogger(SmartHomeSkillV2Handler.clreplaced);
private static final String CODE_BUSY = "DEVICE_BUSY";
private static final String CODE_LOW_BATTERY = "LOW_BATTERY";
private final ShsConfig config;
private final PlatformBusClient busClient;
private final ExecutorService executor;
private final HealthCheckDirectiveHandler healthCheckHandler;
private final VoiceBridgeMetrics metrics;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public SmartHomeSkillV2Handler(ShsConfig config, PlatformMessageBus bus, @Named(VoiceBridgeConfig.NAME_EXECUTOR) ExecutorService executor, HealthCheckDirectiveHandler healthCheckHandler, VoiceBridgeMetrics metrics, PlacePopulationCacheManager populationCacheMgr) {
this.config = config;
this.busClient = new PlatformBusClient(bus, executor, ImmutableSet.of(AddressMatchers.equals(AlexaUtil.ADDRESS_BRIDGE)));
this.executor = executor;
this.healthCheckHandler = healthCheckHandler;
this.metrics = metrics;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public boolean supports(AlexaMessage message) {
return message.getHeader().isV2();
}
@Override
public ListenableFuture<AlexaMessage> handle(AlexaMessage message, UUID placeId) {
if (message.getPayload() instanceof HealthCheckRequest) {
ShsMetrics.incHealthCheck();
return Futures.transform(healthCheckHandler.handle(), (Function<ResponsePayload, AlexaMessage>) input -> {
Preconditions.checkNotNull(input, "input cannot be null");
Header h = Header.v2(message.getHeader().getMessageId(), input.getName(), input.getNamespace());
return new AlexaMessage(h, input);
}, MoreExecutors.directExecutor());
}
if (message.getPayload() instanceof RequestPayload) {
ShsMetrics.incShsRequest();
long startTime = System.nanoTime();
Txfm txfm = Txfm.transformerFor(message);
PlatformMessage platformMessage = txfm.txfmRequest(message, placeId, populationCacheMgr.getPopulationByPlaceId(placeId), (int) config.getRequestTimeoutMs());
logger.debug("[{}] transformed to platform message [{}]", message, platformMessage);
return Futures.transformAsync(busClient.request(platformMessage), (AsyncFunction<PlatformMessage, AlexaMessage>) input -> {
metrics.timeServiceSuccess(platformMessage.getMessageType(), startTime);
return Futures.immediateFuture(txfm.transformResponse(message, input));
}, executor);
} else {
logger.warn("received non-directive request from Alexa {}", message);
ShsMetrics.incNonDirective();
return Futures.immediateFailedFuture(new AlexaException(AlexaErrors.unsupportedDirective(message.getHeader().getName())));
}
}
@Override
public AlexaMessage transformException(AlexaMessage message, Throwable e) {
logger.warn("an exception occured handling {}", message, e);
Payload p = new DriverInternalError();
Throwable cause = e;
if (e instanceof ExecutionException) {
cause = e.getCause();
}
if (cause instanceof ErrorPayloadException) {
p = ((ErrorPayloadException) cause).getPayload();
}
if (cause instanceof AlexaException) {
p = transformAlexaError(message, ((AlexaException) cause).getErrorMessage());
}
String namespace = p.getNamespace();
if (p instanceof BridgeOfflineError && Payload.QUERY_NAMESPACE.equals(message.getHeader().getNamespace())) {
namespace = Payload.QUERY_NAMESPACE;
}
Header h = Header.v2(message.getHeader().getMessageId(), p.getName(), namespace);
return new AlexaMessage(h, p);
}
@Override
public Optional<String> extractOAuthToken(AlexaMessage message) {
if (!(message.getPayload() instanceof RequestPayload)) {
return Optional.empty();
}
return Optional.ofNullable(((RequestPayload) message.getPayload()).getAccessToken());
}
@SuppressWarnings("unchecked")
private ErrorPayload transformAlexaError(AlexaMessage message, MessageBody body) {
String type = AlexaService.AlexaErrorEvent.getType(body);
switch(type) {
case AlexaErrors.TYPE_BRIDGE_UNREACHABLE:
return new BridgeOfflineError();
case AlexaErrors.TYPE_DUAL_SETPOINTS_UNSUPPORTED:
return new UnsupportedTargetSettingError();
case AlexaErrors.TYPE_ENDPOINT_BUSY:
if (Payload.QUERY_NAMESPACE.equals(message.getHeader().getNamespace())) {
return new UnableToGetValueError(CODE_BUSY, "Device is busy and cannot respond.");
}
return new UnableToSetValueError(CODE_BUSY, "Device is busy and cannot be controlled.");
case AlexaErrors.TYPE_ENDPOINT_LOW_POWER:
if (Payload.QUERY_NAMESPACE.equals(message.getHeader().getNamespace())) {
return new UnableToGetValueError(CODE_LOW_BATTERY, "Device's battery is too low to respond.");
}
return new UnableToSetValueError(CODE_LOW_BATTERY, "Device's battery is too low and cannot be controlled.");
case AlexaErrors.TYPE_ENDPOINT_UNREACHABLE:
return new TargetOfflineError();
case AlexaErrors.TYPE_EXPIRED_AUTHORIZATION_CREDENTIAL:
return new ExpiredAccessTokenError();
case AlexaErrors.TYPE_FIRMWARE_OUT_OF_DATE:
return new TargetFirmwareOutdatedError();
case AlexaErrors.TYPE_HARDWARE_MALFUNCTION:
return new TargetHardwareMalfunctionError();
case AlexaErrors.TYPE_INTERNAL_ERROR:
return new DriverInternalError();
case AlexaErrors.TYPE_INVALID_AUTHORIZATION_CREDENTIAL:
return new InvalidAccessTokenError();
case AlexaErrors.TYPE_INVALID_DIRECTIVE:
return new UnsupportedOperationError();
case AlexaErrors.TYPE_INVALID_VALUE:
return new UnsupportedTargetSettingError();
case AlexaErrors.TYPE_NO_SUCH_ENDPOINT:
return new UnsupportedTargetError();
case AlexaErrors.TYPE_NOT_SUPPORTED_IN_CURRENT_MODE:
String mode = (String) AlexaService.AlexaErrorEvent.getPayload(body).getOrDefault("currentDeviceMode", "OTHER");
return new NotSupportedInCurrentModeError(mode);
case AlexaErrors.TYPE_RATE_LIMIT_EXCEEDED:
return new RateLimitExceededError();
case AlexaErrors.TYPE_REQUESTED_SETPOINTS_TOO_CLOSE:
return new UnsupportedTargetSettingError();
case AlexaErrors.TYPE_TEMPERATURE_VALUE_OUT_OF_RANGE:
{
Map<String, Object> payload = AlexaService.AlexaErrorEvent.getPayload(body);
AlexaValidRange range = new AlexaValidRange((Map<String, Object>) payload.get(AlexaErrors.PROP_VALIDRANGE));
AlexaTemperature min = new AlexaTemperature((Map<String, Object>) range.getMinimumValue());
AlexaTemperature max = new AlexaTemperature((Map<String, Object>) range.getMaximumValue());
return new ValueOutOfRangeError(min.getValue(), max.getValue());
}
case AlexaErrors.TYPE_THERMOSTAT_IS_OFF:
case AlexaErrors.TYPE_UNWILLING_TO_SET_VALUE:
return new UnwillingToSetValueError("ThermostatIsOff", "The thermostat is off and cannot be turned on to complete request.");
case AlexaErrors.TYPE_TRIPLE_SETPOINTS_UNSUPPORTED:
return new UnsupportedTargetSettingError();
case AlexaErrors.TYPE_UNSUPPORTED_THERMOSTAT_MODE:
return new UnsupportedTargetSettingError();
case AlexaErrors.TYPE_VALUE_OUT_OF_RANGE:
Map<String, Object> payload = AlexaService.AlexaErrorEvent.getPayload(body);
AlexaValidRange range = new AlexaValidRange((Map<String, Object>) payload.get(AlexaErrors.PROP_VALIDRANGE));
Double min = ((Number) range.getMinimumValue()).doubleValue();
Double max = ((Number) range.getMaximumValue()).doubleValue();
return new ValueOutOfRangeError(min, max);
default:
return new DriverInternalError();
}
}
}
17
Source : CallTreeExecutor.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced CallTreeExecutor {
private static final Logger logger = LoggerFactory.getLogger(CallTreeExecutor.clreplaced);
private final PlatformMessageBus bus;
private final ConcurrentMap<SequentialCallTaskKey, SequentialCallTask> sequentialTasks = new ConcurrentHashMap<>();
private final HashedWheelTimer sequentialTimer = new HashedWheelTimer(new ThreadFactoryBuilder().setDaemon(true).setNameFormat("calltree-sequential-%d").setUncaughtExceptionHandler(new LoggingUncaughtExceptionHandler(logger)).build());
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public CallTreeExecutor(PlatformMessageBus bus, PlacePopulationCacheManager populationCacheMgr) {
this.bus = bus;
this.populationCacheMgr = populationCacheMgr;
}
public void startSequential(CallTreeContext context) {
Preconditions.checkArgument(context.getSequentialDelaySecs() > 0, "sequential delay must be greater than 0 seconds");
SequentialCallTaskKey key = new SequentialCallTaskKey(context.getIncidentAddress(), context.getMsgKey());
SequentialCallTask task = new SequentialCallTask(key, context);
SequentialCallTask existing = sequentialTasks.putIfAbsent(key, task);
if (existing != null) {
logger.debug("{}: ignoring request to start sequential call tree already in progress", key);
return;
}
sequentialTimer.newTimeout(task, 0, TimeUnit.MILLISECONDS);
}
public void stopSequential(Address incidentAddress, String msgKey) {
SequentialCallTaskKey key = new SequentialCallTaskKey(incidentAddress, msgKey);
SequentialCallTask task = sequentialTasks.remove(key);
if (task != null) {
task.cancel();
}
}
public void notifyParallel(CallTreeContext context) {
context.getCallTree().stream().filter(CallTreeEntry::getEnabled).forEach(entry -> notifyPerson(context, entry.getPerson()));
}
public void notifyOwner(CallTreeContext context) {
notifyPerson(context, context.getCallTree().get(0).getPerson());
}
private void notifyPerson(CallTreeContext context, String address) {
notifyPerson(context, Address.fromString(address));
}
private void notifyPerson(CallTreeContext context, Address personAddress) {
NotificationCapability.NotifyRequest.Builder builder = NotificationCapability.NotifyRequest.builder().withMsgKey(context.getMsgKey()).withPlaceId(context.getPlaceId().toString()).withPersonId(personAddress.getId().toString()).withPriority(context.getPriority());
if (!context.getParams().isEmpty()) {
builder.withMsgParams(context.getParams());
}
MessageBody body = builder.build();
PlatformMessage message = PlatformMessage.builder().from(NotificationConstants.ALARMSERVICE_ADDRESS).to(NotificationConstants.NOTIFICATIONSERVICE_ADDRESS).withPlaceId(context.getPlaceId()).withPopulation(populationCacheMgr.getPopulationByPlaceId(context.getPlaceId())).withActor(NotificationConstants.ALARMSERVICE_ADDRESS).withPayload(body).create();
bus.send(message);
}
private clreplaced SequentialCallTaskKey {
private final Address incidentAddress;
private final String msgKey;
SequentialCallTaskKey(Address incidentAddress, String msgKey) {
this.incidentAddress = incidentAddress;
this.msgKey = msgKey;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClreplaced() != o.getClreplaced())
return false;
SequentialCallTaskKey that = (SequentialCallTaskKey) o;
if (incidentAddress != null ? !incidentAddress.equals(that.incidentAddress) : that.incidentAddress != null)
return false;
return msgKey != null ? msgKey.equals(that.msgKey) : that.msgKey == null;
}
@Override
public int hashCode() {
int result = incidentAddress != null ? incidentAddress.hashCode() : 0;
result = 31 * result + (msgKey != null ? msgKey.hashCode() : 0);
return result;
}
@Override
public String toString() {
return incidentAddress.getRepresentation() + "-" + msgKey;
}
}
private clreplaced SequentialCallTask implements TimerTask {
private final SequentialCallTaskKey key;
private final CallTreeContext context;
private volatile boolean cancelled = false;
private volatile int index = 0;
private volatile Timeout nextTimeout = null;
SequentialCallTask(SequentialCallTaskKey key, CallTreeContext context) {
this.key = key;
this.context = context;
}
@Override
public void run(Timeout timeout) throws Exception {
if (cancelled) {
logger.debug("{}: sequential call tree stopping because it has been cancelled", key);
return;
}
String person = nextPerson();
if (person != null) {
notifyPerson(context, person);
this.nextTimeout = sequentialTimer.newTimeout(this, context.getSequentialDelaySecs(), TimeUnit.SECONDS);
} else {
logger.debug("{}: sequential call tree terminated with no additional people to call", key);
sequentialTasks.remove(key);
}
}
String nextPerson() {
List<CallTreeEntry> entries = context.getCallTree();
if (index >= entries.size()) {
return null;
}
do {
CallTreeEntry entry = entries.get(index++);
if (entry.getEnabled()) {
return entry.getPerson();
}
} while (index < entries.size());
return null;
}
void cancel() {
if (cancelled) {
return;
}
cancelled = true;
if (this.nextTimeout != null && !this.nextTimeout.isCancelled()) {
this.nextTimeout.cancel();
}
}
}
}
16
Source : IpcdSession.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
public abstract clreplaced IpcdSession extends DefaultSessionImpl implements ParreplacedionedSession {
private final static Logger logger = LoggerFactory.getLogger(IpcdSession.clreplaced);
private volatile IpcdDevice.RegistrationState registrationState;
private volatile PlatformParreplacedion parreplacedion;
protected final IpcdDeviceDao ipcdDeviceDao;
protected final ProtocolBusService protocolBusService;
protected final DeviceDAO deviceDao;
protected final PlaceDAO placeDao;
protected final PlatformMessageBus platformBus;
protected final Parreplacedioner parreplacedioner;
protected final PlacePopulationCacheManager populationCacheMgr;
public IpcdSession(SessionRegistry parent, IpcdDeviceDao ipcdDeviceDao, DeviceDAO deviceDao, PlaceDAO placeDao, Channel channel, PlatformMessageBus platformBus, ProtocolBusService protocolBusService, Parreplacedioner parreplacedioner, BridgeMetrics bridgeMetrics, PlacePopulationCacheManager populationCacheMgr) {
super(parent, channel, bridgeMetrics);
this.ipcdDeviceDao = ipcdDeviceDao;
this.deviceDao = deviceDao;
this.placeDao = placeDao;
this.platformBus = platformBus;
this.protocolBusService = protocolBusService;
this.parreplacedioner = parreplacedioner;
this.populationCacheMgr = populationCacheMgr;
}
public abstract void sendMessage(IpcdMessage msg);
public void initializeSession(Device device) {
initializeSession(device, null);
}
public void initializeSession(Device device, DeviceInfo deviceInfo) {
logger.debug("Initializing IPCD Session with Device {}", device);
Address protocolAddress = IpcdProtocol.ipcdAddress(device);
IpcdDevice ipcdDevice = getOrCreateIpcdDevice(protocolAddress.getRepresentation(), device, deviceInfo);
setClientToken(IpcdClientToken.fromProtocolAddress(protocolAddress));
if (ipcdDevice.getPlaceId() == null) {
SessionUtil.clearPlace(this);
} else {
SessionUtil.setPlace(ipcdDevice.getPlaceId(), this);
}
this.registrationState = ipcdDevice.getRegistrationState();
reportOnline(ipcdDevice.getDevice());
}
public IpcdDevice.RegistrationState getRegistrationState() {
return registrationState;
}
@Override
public PlatformParreplacedion getParreplacedion() {
return parreplacedion;
}
@Override
public void setActivePlace(String placeId) {
super.setActivePlace(placeId);
this.parreplacedion = placeId == null ? new DefaultParreplacedion(0) : parreplacedioner.getParreplacedionForPlaceId(placeId);
}
public void claim(String accountId, String placeId, String population) {
setActivePlace(placeId);
this.registrationState = IpcdDevice.RegistrationState.PENDING_DRIVER;
}
public void register(String accountId, String placeId, String population, String driverAddress) {
this.setActivePlace(placeId);
this.registrationState = IpcdDevice.RegistrationState.REGISTERED;
}
public void unregister() {
SessionUtil.clearPlace(this);
this.registrationState = IpcdDevice.RegistrationState.UNREGISTERED;
}
public void onFactoryReset() {
SessionUtil.clearPlace(this);
}
private void reportOnline(Device device) {
if (getActivePlace() != null) {
ProtocolMessage onlineMsg = ProtocolMessage.builder().broadcast().from(getClientToken().getRepresentation()).withPlaceId(getActivePlace()).withPopulation(populationCacheMgr.getPopulationByPlaceId(getActivePlace())).withPayload(ControlProtocol.INSTANCE, DeviceOnlineEvent.create()).create();
protocolBusService.placeMessageOnProtocolBus(onlineMsg);
MessageBody connectedMsg = IpcdService.DeviceConnectedEvent.builder().withProtocolAddress(getClientToken().getRepresentation()).build();
PlatformMessage msg = PlatformMessage.buildMessage(connectedMsg, Address.bridgeAddress(IpcdProtocol.NAMESPACE), Address.platformService(IpcdService.NAMESPACE)).withActor(Address.clientAddress("ipcd-bridge", String.valueOf(parreplacedioner.getMemberId()))).withPlaceId(getActivePlace()).withPopulation(populationCacheMgr.getPopulationByPlaceId(getActivePlace())).create();
platformBus.send(msg);
}
}
protected void onReportOnline(Device device) {
}
private IpcdDevice getOrCreateIpcdDevice(String protocolAddress, Device device, DeviceInfo deviceInfo) {
if (isMixedCase(device.getSn())) {
logger.warn("[{}] has a mixed case SN, which will almost certainly cause an issue registering the device", device);
}
IpcdDevice ipcdDevice = ipcdDeviceDao.findByProtocolAddress(protocolAddress);
if (ipcdDevice == null) {
ipcdDevice = new IpcdDevice();
ipcdDevice.setProtocolAddress(protocolAddress);
}
ipcdDevice.updateWithDevice(device);
if (deviceInfo != null) {
ipcdDevice.updateWithDeviceInfo(deviceInfo);
}
// Make sure the ipcd-device table is in sync with the device table.
ipcdDevice = syncIpcdDeviceToIrisDevice(ipcdDevice);
ipcdDevice.setConnState(ConnState.ONLINE);
ipcdDevice.setLastConnected(new Date());
ipcdDeviceDao.save(ipcdDevice);
return ipcdDevice;
}
private IpcdDevice syncIpcdDeviceToIrisDevice(IpcdDevice ipcdDevice) {
com.iris.messages.model.Device irisDevice = deviceDao.findByProtocolAddress(ipcdDevice.getProtocolAddress());
if (irisDevice != null) {
ipcdDevice.syncToIrisDevice(irisDevice);
}
return ipcdDevice;
}
private boolean isMixedCase(String sn) {
return CharMatcher.JAVA_LOWER_CASE.matchesAnyOf(sn) && CharMatcher.JAVA_UPPER_CASE.matchesAnyOf(sn);
}
}
16
Source : AbstractZWaveDriverTest.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Mocks({ DeviceDAO.clreplaced, PlacePopulationCacheManager.clreplaced })
@Modules({ InMemoryMessageModule.clreplaced, CapabilityRegistryModule.clreplaced, GroovyProtocolPluginModule.clreplaced })
public abstract clreplaced AbstractZWaveDriverTest extends IrisMockTestCase implements DriverTestContext<ZWaveMessage> {
@Inject
protected PlatformMessageBus platformBus;
@Inject
protected PlacePopulationCacheManager mockPopulationCacheMgr;
@Inject
protected ProtocolMessageBus protocolBus;
@Inject
protected CapabilityRegistry capabilityRegistry;
@Inject
protected GroovyDriverFactory factory;
private final ClientAddress clientAddress = Fixtures.createClientAddress();
private final Address driverAddress = Fixtures.createDeviceAddress();
private final Address protocolAddress = Fixtures.createProtocolAddress();
private Device device;
private DeviceDriver deviceDriver;
private DeviceDriverContext deviceDriverContext;
@Provides
public GroovyScriptEngine scriptEngine(CapabilityRegistry capabilityRegistry) {
GroovyScriptEngine engine = new GroovyScriptEngine(new ClreplacedpathResourceConnector());
engine.getConfig().addCompilationCustomizers(new DriverCompilationCustomizer(capabilityRegistry));
return engine;
}
@Override
public Address getProtocolAddress() {
return protocolAddress;
}
@Override
public Address getDriverAddress() {
return driverAddress;
}
@Override
public Protocol<ZWaveMessage> getProtocol() {
return ZWaveProtocol.INSTANCE;
}
@Override
public DeviceDriverContext getDeviceDriverContext() {
return deviceDriverContext;
}
@Override
public DeviceDriver getDeviceDriver() {
return deviceDriver;
}
@Override
public ClientAddress getClientAddress() {
return clientAddress;
}
@Override
public InMemoryPlatformMessageBus getPlatformBus() {
return (InMemoryPlatformMessageBus) platformBus;
}
@Override
public InMemoryProtocolMessageBus getProtocolBus() {
return (InMemoryProtocolMessageBus) protocolBus;
}
@Override
public CapabilityRegistry getCapabilityRegistry() {
return capabilityRegistry;
}
@Override
public ZWaveNode getDevice() {
ZWaveNode node = new ZWaveNode((byte) 10);
return node;
}
public void initializeDriver(String driverScriptResource) throws Exception {
deviceDriver = factory.load(driverScriptResource);
device = createDeviceFromDriver(deviceDriver);
deviceDriverContext = new PlatformDeviceDriverContext(device, deviceDriver, mockPopulationCacheMgr);
}
@SuppressWarnings("unchecked")
private Device createDeviceFromDriver(DeviceDriver driver) {
Device device = Fixtures.createDevice();
for (AttributeKey<?> thisKey : driver.getBaseAttributes().keySet()) {
Object thisValue = driver.getBaseAttributes().get(thisKey);
switch(thisKey.getName()) {
case "devadv:drivername":
device.setDrivername((String) thisValue);
break;
case "devadv:protocol":
device.setProtocol((String) thisValue);
break;
case "dev:devtypehint":
device.setDevtypehint((String) thisValue);
break;
case "base:caps":
device.setCaps((Set<String>) thisValue);
break;
case "dev:vendor":
device.setVendor((String) thisValue);
break;
case "dev:model":
device.setModel((String) thisValue);
break;
}
}
device.setDriverversion(driver.getDefinition().getVersion());
return device;
}
}
16
Source : TestAlarmIncidentServiceImpl.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Modules(InMemoryMessageModule.clreplaced)
@Mocks(value = { AlarmIncidentDAO.clreplaced, AlarmIncidentHistoryListener.clreplaced, HistoryLogDAO.clreplaced, SubsystemExecutor.clreplaced, SubsystemRegistry.clreplaced, PlatformAlarmIncidentService.clreplaced, PlacePopulationCacheManager.clreplaced })
public clreplaced TestAlarmIncidentServiceImpl extends IrisMockTestCase {
@Inject
InMemoryPlatformMessageBus messageBus;
@Inject
SubsystemRegistry registry;
@Inject
SubsystemExecutor executor;
@Inject
AlarmIncidentDAO alarmIncidentDao;
@Inject
HistoryLogDAO historyLogDao;
@Inject
AlarmIncidentServiceImpl service;
@Inject
protected PlacePopulationCacheManager mockPopulationCacheMgr;
UUID placeId = UUID.randomUUID();
AlarmIncident incident = IncidentFixtures.createPreAlert(ServiceLevel.PREMIUM_PROMON);
@Provides
@Named(AlarmIncidentServiceImpl.NAME_EXECUTOR_POOL)
public ExecutorService executor() {
return ThreadPoolBuilder.newSingleThreadedScheduler("test-alarm-incident");
}
@Before
public void setupMocks() {
EasyMock.expect(mockPopulationCacheMgr.getPopulationByPlaceId(EasyMock.anyObject(UUID.clreplaced))).andReturn(Population.NAME_GENERAL).anyTimes();
}
protected PlatformMessage getAttributes() {
return PlatformMessage.request(incident.getAddress()).from(Fixtures.createClientAddress()).withPlaceId(placeId).withPayload(Capability.CMD_GET_ATTRIBUTES).create();
}
protected PlatformMessage verifyRequest() {
return PlatformMessage.request(incident.getAddress()).from(Fixtures.createClientAddress()).withPlaceId(placeId).withPayload(VerifyRequest.instance()).create();
}
protected PlatformMessage listHistory() {
return PlatformMessage.request(incident.getAddress()).from(Fixtures.createClientAddress()).withPlaceId(placeId).withPayload(ListHistoryEntriesRequest.builder().build()).create();
}
protected IExpectationSetters<Optional<SubsystemExecutor>> expectGetSubsystem() {
return EasyMock.expect(registry.loadByPlace(placeId));
}
protected IExpectationSetters<AlarmIncident> expectFindAlarmIncidentById() {
return EasyMock.expect(alarmIncidentDao.findById(placeId, incident.getId()));
}
@After
public void verify() {
super.verify();
}
@Test
public void testGetAttributes() throws Exception {
expectFindAlarmIncidentById().andReturn(incident);
PlatformMessage request = getAttributes();
replay();
service.handleMessage(request);
PlatformMessage message = messageBus.take();
replacedertEquals(Capability.EVENT_GET_ATTRIBUTES_RESPONSE, message.getMessageType());
verify();
}
@Test
public void testGetAttributesAlarmIncidentNotFound() throws Exception {
expectFindAlarmIncidentById().andReturn(null);
PlatformMessage request = getAttributes();
replay();
service.handleMessage(request);
PlatformMessage message = messageBus.take();
replacedertEquals(ErrorEvent.MESSAGE_TYPE, message.getMessageType());
replacedertEquals(Errors.CODE_NOT_FOUND, message.getValue().getAttributes().get(ErrorEvent.CODE_ATTR));
verify();
}
@Test
public void testGetAttributesAlarmIncidentException() throws Exception {
expectFindAlarmIncidentById().andThrow(new RuntimeException("BOOM"));
PlatformMessage request = getAttributes();
replay();
service.handleMessage(request);
PlatformMessage message = messageBus.take();
replacedertEquals(ErrorEvent.MESSAGE_TYPE, message.getMessageType());
}
@Test
public void testSubsystemExecutorFound() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
expectGetSubsystem().andReturn(Optional.of(executor));
PlatformMessage request = verifyRequest();
executor.onPlatformMessage(request);
EasyMock.expectLastCall().andAnswer(() -> {
latch.countDown();
return null;
});
replay();
service.handleMessage(request);
replacedertTrue(latch.await(100, TimeUnit.MILLISECONDS));
replacedertEquals(null, messageBus.poll());
}
@Test
public void testSubsystemExecutorNotFound() throws Exception {
expectGetSubsystem().andReturn(Optional.empty());
PlatformMessage request = verifyRequest();
replay();
service.handleMessage(request);
PlatformMessage message = messageBus.take();
replacedertEquals(ErrorEvent.MESSAGE_TYPE, message.getMessageType());
replacedertEquals(Errors.CODE_NOT_FOUND, message.getValue().getAttributes().get(ErrorEvent.CODE_ATTR));
}
@Test
public void testListHistoryEntries() throws Exception {
PlatformMessage request = listHistory();
EasyMock.expect(historyLogDao.listEntriesByQuery(EasyMock.notNull())).andReturn(PagedResults.emptyPage());
replay();
service.handleMessage(request);
PlatformMessage message = messageBus.take();
replacedertEquals(ListHistoryEntriesResponse.NAME, message.getMessageType());
}
}
16
Source : AlarmIncidentServiceTestCase.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Mocks({ AlarmIncidentDAO.clreplaced, AlarmIncidentHistoryListener.clreplaced, SubsystemRegistry.clreplaced, PlacePopulationCacheManager.clreplaced })
@Modules(InMemoryMessageModule.clreplaced)
public clreplaced AlarmIncidentServiceTestCase extends IrisMockTestCase {
protected SubsystemContext<AlarmSubsystemModel> context;
protected SimpleModelStore models = new SimpleModelStore();
protected UUID placeId;
protected Address cancelledBy = Address.platformService(UUID.randomUUID(), PersonCapability.NAMESPACE);
protected ServiceLevel serviceLevel;
@Inject
protected InMemoryPlatformMessageBus bus;
@Inject
protected AlarmIncidentDAO incidentDao;
@Inject
protected AlarmIncidentHistoryListener incidentHistory;
@Inject
protected PlacePopulationCacheManager mockPopulationCacheMgr;
public AlarmIncidentServiceTestCase(String serviceLevel) {
this.serviceLevel = ServiceLevel.valueOf(serviceLevel);
}
@Before
public void createSubsystemContext() throws Exception {
Map<String, Object> place = ModelFixtures.createPlaceAttributes();
place.put(PlaceCapability.ATTR_SERVICELEVEL, serviceLevel.name());
models.addModel(place);
placeId = UUID.fromString((String) place.get(Capability.ATTR_ID));
context = PlatformSubsystemContext.builder().withAccountId(UUID.randomUUID()).withPlaceId(placeId).withPopulation(Population.NAME_GENERAL).withLogger(LoggerFactory.getLogger(TestPlatformAlarmIncidentService.clreplaced)).withPlatformBus(bus).withModels(models).build(AlarmSubsystemModel.clreplaced, new ModelEnreplacedy(ModelFixtures.buildSubsystemAttributes(placeId, AlarmSubsystemCapability.NAMESPACE).create()));
EasyMock.expect(mockPopulationCacheMgr.getPopulationByPlaceId(EasyMock.anyObject(UUID.clreplaced))).andReturn(Population.NAME_GENERAL).anyTimes();
}
protected void expectCurrentAndReturnNull() {
expectCurrentAndReturn(null);
}
protected void expectCurrentAndReturn(AlarmIncident incident) {
EasyMock.expect(incidentDao.current(placeId)).andReturn(incident);
}
protected void expectGetActiveAndReturnNull(UUID incidentId) {
expectFindByAndReturnNull(incidentId);
}
protected void expectGetActiveAndReturn(AlarmIncident incident) {
expectFindByAndReturn(incident);
}
protected void expectFindByAndReturnNull(UUID incidentId) {
EasyMock.expect(incidentDao.findById(placeId, incidentId)).andReturn(null);
}
protected void expectFindByAndReturn(AlarmIncident incident) {
EasyMock.expect(incidentDao.findById(placeId, incident.getId())).andReturn(incident);
}
protected void expectFindByAndReturn(UUID incidentId, Capture<AlarmIncident> incident) {
EasyMock.expect(incidentDao.findById(placeId, incidentId)).andAnswer(() -> incident.getValue());
}
protected Capture<AlarmIncident> expectUpdate() {
Capture<AlarmIncident> captor = EasyMock.newCapture();
incidentDao.upsert(EasyMock.capture(captor));
EasyMock.expectLastCall();
return captor;
}
protected List<Capture<AlarmIncident>> expectUpdate(int times) {
ArrayList<Capture<AlarmIncident>> list = new ArrayList<Capture<AlarmIncident>>(times);
for (int i = 0; i < times; i++) {
Capture<AlarmIncident> captor = EasyMock.newCapture();
incidentDao.upsert(EasyMock.capture(captor));
EasyMock.expectLastCall();
list.add(captor);
}
return list;
}
protected void expectTriggersAdded(AlarmIncident incident, List<IncidentTrigger> triggers) {
incidentHistory.onTriggersAdded(context, incident.getAddress(), triggers);
EasyMock.expectLastCall();
}
protected void expectCancelling(AlarmIncident incident, Address cancelledBy, String method) {
incidentHistory.onCancelled(context, incident, cancelledBy, method);
EasyMock.expectLastCall();
}
protected void replacedertBroadcastAdded(AlarmIncident incident) {
PlatformMessage message = bus.poll();
replacedertEquals(Capability.EVENT_ADDED, message.getMessageType());
replacedertAlarmIncidentBroadcaseValues(incident, message.getValue());
}
protected void replacedertBroadcastChanged(AlarmIncident incident) {
PlatformMessage message = bus.poll();
replacedertEquals(Capability.EVENT_VALUE_CHANGE, message.getMessageType());
}
protected void replacedertAlarmIncidentBroadcaseValues(AlarmIncident incident, MessageBody body) {
// replacedertEquals(incident.getMonitoringState().name(), AlarmIncidentCapability.getMonitoringState(body) );
replacedertEquals(incident.isMonitored(), AlarmIncidentCapability.getMonitored(body));
}
protected void replacedertBroadcastAlert(AlertType alert, List<IncidentTrigger> triggers) {
String eventType = AlarmIncident.toEvent(alert);
PlatformMessage message = bus.poll();
replacedertEquals(eventType, message.getMessageType());
Object expectedTriggers = JSON.fromJson(JSON.toJson(IrisCollections.transform(triggers, IncidentTrigger::toMap)), Object.clreplaced);
replacedertEquals(expectedTriggers, COAlertEvent.getTriggers(message.getValue()));
}
protected void replacedertAddAlarm(AlertType type) {
PlatformMessage message = bus.poll();
replacedertNotNull(message);
replacedertEquals(AlarmService.AddAlarmRequest.NAME, message.getMessageType());
replacedertEquals(type.name(), AddAlarmRequest.getAlarm(message.getValue()));
// FIXME other alarms and triggers should be verified
}
protected void replacedertNoMessages() {
replacedertNull(bus.poll());
}
protected void replacedertAddAlarm(AlarmIncident incident, AlertType primary, List<AlertType> expectedAlerts, List<IncidentTrigger> triggers) {
PlatformMessage message = bus.poll();
MessageBody value = message.getValue();
replacedertEquals(AlarmService.AddAlarmRequest.NAME, message.getMessageType());
replacedertEquals(primary.name(), AlarmService.AddAlarmRequest.getAlarm(value));
{
List<String> expectedAlarms = expectedAlerts.stream().map(AlertType::name).collect(Collectors.toList());
List<String> actualAlarms = AlarmService.AddAlarmRequest.getAlarms(value);
replacedertEquals(expectedAlarms, actualAlarms);
}
{
List<Map<String, Object>> expectedTriggers = (List<Map<String, Object>>) JSON.fromJson(JSON.toJson(triggers.stream().map(IncidentTrigger::toMap).collect(Collectors.toList())), Object.clreplaced);
List<Map<String, Object>> actualTriggers = AlarmService.AddAlarmRequest.getTriggers(value);
replacedertEquals(expectedTriggers, actualTriggers);
}
}
protected void replacedertIncidentTrackers(AlarmIncident incident, TrackerState... states) {
int i = 0;
for (TrackerEvent event : incident.getTracker()) {
if (i >= states.length) {
fail("Unexpected tracker events: " + incident.getTracker().subList(states.length, incident.getTracker().size()));
}
replacedertEquals(String.format("Expected: %s but was: %s at index: %d", states[i], event.getState(), i), states[i].name(), event.getState());
replacedertTrackerEvent(event);
i++;
}
if (i < states.length) {
fail("Missing tracker events: " + Arrays.asList(states).subList(i, states.length));
}
}
protected void replacedertTrackerEvent(TrackerEvent event) {
replacedertNotNull(event);
replacedertNotNull(event.getState());
replacedertNotNull(event.getTime());
replacedertTrue(StringUtils.isNotBlank(event.getKey()));
if (StringUtils.isBlank(event.getMessage())) {
if (StringUtils.isNotBlank(PlatformAlarmIncidentService.getEventMessage(event.getKey()))) {
fail("message should not be null for key " + event.getKey());
}
}
}
protected void replacedertIncidentPreAlert(AlarmIncident incident, Date prealertEndTime) {
replacedertEquals(AlertType.SECURITY, incident.getAlert());
replacedertEquals(AlertState.PREALERT, incident.getAlertState());
replacedertEquals(AlertState.PREALERT, incident.getPlatformAlertState());
replacedertEquals(MonitoringState.NONE, incident.getMonitoringState());
replacedertEquals(prealertEndTime, incident.getPrealertEndTime());
replacedertNotCancelled(incident);
}
protected void replacedertIncidentAlert(AlarmIncident incident, AlertType primary, AlertType... additional) {
replacedertEquals(AlertState.ALERT, incident.getAlertState());
replacedertEquals(AlertState.ALERT, incident.getPlatformAlertState());
replacedertEquals(primary, incident.getAlert());
replacedertEquals(ImmutableSet.copyOf(additional), incident.getAdditionalAlerts());
replacedertNotCancelled(incident);
}
protected void replacedertNotCancelled(AlarmIncident incident) {
replacedertNull(incident.getCancelledBy());
replacedertNull(incident.getEndTime());
}
protected void replacedertIncidentMonitored(AlarmIncident incident) {
if (ServiceLevel.isPromon(this.serviceLevel)) {
replacedertTrue(incident.isMonitored());
} else {
replacedertFalse(incident.isMonitored());
}
}
}
16
Source : TestCachingSubsystemRegistry.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
/**
*/
@Mocks({ SubsystemExecutor.clreplaced, SubsystemFactory.clreplaced, PlaceDAO.clreplaced, ModelDao.clreplaced, PlacePopulationCacheManager.clreplaced })
public clreplaced TestCachingSubsystemRegistry extends IrisMockTestCase {
@Inject
CachingSubsystemRegistry registry;
@Inject
SubsystemExecutor mockExecutor;
@Inject
SubsystemFactory mockFactory;
@Inject
PlaceDAO mockPlaceDao;
@Inject
ModelDao mockModelDao;
@Inject
protected PlacePopulationCacheManager mockPopulationCacheMgr;
UUID placeId = UUID.randomUUID();
Place place = Fixtures.createPlace();
List<Model> models = new ArrayList<>();
@Before
public void setUp() throws Exception {
super.setUp();
place.setId(placeId);
place.setCreated(new Date());
place.setModified(new Date());
place.setTzName("UTC");
models.add(createDeviceModel());
models.add(createDeviceModel());
models.add(createDeviceModel());
EasyMock.expect(mockPopulationCacheMgr.getPopulationByPlaceId(EasyMock.anyObject(UUID.clreplaced))).andReturn(Population.NAME_GENERAL).anyTimes();
}
@Test
public void testFindByPlaceId() {
expectPlaceFound();
expectListModels();
Capture<PlaceContext> contextRef = expectCreateContext();
expectExecutorStart();
replay();
SubsystemExecutor executor = registry.loadByPlace(placeId).get();
replacedertEquals(mockExecutor, executor);
PlaceContext context = contextRef.getValue();
replacedertEquals(placeId, context.getPlaceId());
replacedertEquals(place.getAccount(), context.getAccountId());
replacedertEquals(models.size(), context.models().getModels().size());
for (Model model : models) {
Fixtures.replacedertMapEquals(model.toMap(), context.models().getModelByAddress(model.getAddress()).toMap());
}
replacedertNotNull(context.logger());
replacedertNotNull(context.getLocalTime());
verify();
}
@Test
public void testFindByPlaceIdNotFound() {
expectPlaceNotFound();
replay();
Optional<SubsystemExecutor> executor = registry.loadByPlace(placeId);
replacedertFalse(executor.isPresent());
verify();
}
@Test
public void testFindByPlaceIdModelDaoThrowsException() {
expectPlaceFound();
expectListModelsAndThrow();
replay();
Optional<SubsystemExecutor> executor = registry.loadByPlace(placeId);
replacedertFalse(executor.isPresent());
verify();
}
@Test
public void testFindByPlaceAndRemove() throws Exception {
expectListModels();
expectCreateContext();
expectExecutorStart();
expectExecutorStop();
replay();
SubsystemExecutor executor = registry.loadByPlace(place.getId(), place.getAccount()).get();
replacedertEquals(mockExecutor, executor);
registry.removeByPlace(placeId);
verify();
}
@Test
public void testFindByPlaceAndClear() throws Exception {
expectListModels();
expectCreateContext();
expectExecutorStart();
expectExecutorStop();
replay();
SubsystemExecutor executor = registry.loadByPlace(place.getId(), place.getAccount()).get();
replacedertEquals(mockExecutor, executor);
registry.clear();
verify();
}
protected ModelEnreplacedy createDeviceModel() {
Date timestamp = new Date();
UUID id = UUID.randomUUID();
Map<String, Object> attributes = new HashMap<>();
attributes.put(Capability.ATTR_ID, id.toString());
attributes.put(Capability.ATTR_TYPE, DeviceCapability.NAMESPACE);
attributes.put(Capability.ATTR_ADDRESS, Address.platformDriverAddress(id).getRepresentation());
attributes.put(Capability.ATTR_CAPS, ImmutableSet.of(Capability.NAMESPACE, DeviceCapability.NAMESPACE, DeviceAdvancedCapability.NAMESPACE));
ModelEnreplacedy enreplacedy = new ModelEnreplacedy(attributes);
enreplacedy.setCreated(timestamp);
enreplacedy.setModified(timestamp);
return enreplacedy;
}
protected void expectPlaceFound() {
EasyMock.expect(mockPlaceDao.getAccountById(placeId)).andReturn(place.getAccount());
}
protected void expectPlaceNotFound() {
EasyMock.expect(mockPlaceDao.getAccountById(placeId)).andReturn(null);
}
protected Capture<PlaceContext> expectCreateContext() {
Capture<PlaceContext> contextRef = Capture.newInstance();
EasyMock.expect(mockFactory.createExecutor(EasyMock.capture(contextRef))).andReturn(mockExecutor);
EasyMock.expect(mockExecutor.context()).andAnswer(() -> contextRef.getValue()).anyTimes();
return contextRef;
}
protected void expectExecutorStart() {
mockExecutor.start();
EasyMock.expectLastCall();
}
protected void expectExecutorStop() {
mockExecutor.stop();
EasyMock.expectLastCall();
}
protected void expectListModels() {
EasyMock.expect(mockModelDao.loadModelsByPlace(placeId, CachingSubsystemRegistry.TRACKED_TYPES)).andReturn(models);
}
protected void expectListModelsAndThrow() {
EasyMock.expect(mockModelDao.loadModelsByPlace(placeId, CachingSubsystemRegistry.TRACKED_TYPES)).andThrow(new RuntimeException("Error loading models"));
}
}
16
Source : BaseAlarmIncidentService.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
public abstract clreplaced BaseAlarmIncidentService implements AlarmIncidentService {
private static final Logger logger = LoggerFactory.getLogger(BaseAlarmIncidentService.clreplaced);
private static final String VAR_TRIGGER_SENT = "triggerSent";
// FIXME should this be in *.properties?
protected static final Map<String, String> messages = ImmutableMap.<String, String>builder().put("security.prealert", "Grace Period Countdown").put("security.alert", "Alarm Triggered").put("security.cancelled", "").put("security.dispatching", "Monitoring Station Alerted").put("security.dispatched", "Police Notified").put("security.dispatch_refused", "Police Not Responding").put("security.dispatch_cancelled", "Dispatch Cancellation Attempted").put("security.dispatch_failed", "Monitoring Station Unavailable").put("panic.alert", "Alarm Triggered").put("panic.cancelled", "").put("panic.dispatching", "Monitoring Station Alerted").put("panic.dispatched", "Police Notified").put("panic.dispatch_refused", "Police Not Responding").put("panic.dispatch_cancelled", "Police Dispatch Cancelled").put("panic.dispatch_failed", "Monitoring Station Unavailable").put("smoke.alert", "Alarm Triggered").put("smoke.cancelled", "").put("smoke.dispatching", "Monitoring Station Alerted").put("smoke.dispatched", "Fire Dept. Notified").put("smoke.dispatch_refused", "Fire Dept. Not Responding").put("smoke.dispatch_cancelled", "Dispatch Cancellation Attempted").put("smoke.dispatch_failed", "Monitoring Station Unavailable").put("co.alert", "Alarm Triggered").put("co.cancelled", "").put("co.dispatching", "Monitoring Station Alerted").put("co.dispatched", "Fire Dept. Notified").put("co.dispatch_refused", "Fire Dept. Not Responding").put("co.dispatch_cancelled", "Dispatch Cancellation Attempted").put("co.dispatch_failed", "Monitoring Station Unavailable").put("water.alert", "Alarm Triggered").put("water.cancelled", "").build();
private final Set<AlertType> unmonitoredAlertTypes = ImmutableSet.<AlertType>of(AlertType.WATER, AlertType.WEATHER, AlertType.CARE);
private final Predicate<AlertType> isMonitoredPredicate = new Predicate<AlertType>() {
@Override
public boolean apply(AlertType input) {
if (input == null || unmonitoredAlertTypes.contains(input)) {
return false;
} else {
return true;
}
}
};
@Inject(optional = true)
@Named("alarm.incident.maxIncidents")
private int maxIncidents = 25;
private final SubsystemRegistry registry;
protected final AlarmIncidentDAO incidentDao;
protected final AlarmIncidentHistoryListener historyListener;
private final PlatformMessageBus platformBus;
protected final PlacePopulationCacheManager populationCacheMgr;
protected BaseAlarmIncidentService(SubsystemRegistry registry, AlarmIncidentDAO incidentDao, AlarmIncidentHistoryListener historyListener, PlatformMessageBus platformBus, PlacePopulationCacheManager populationCacheMgr) {
this.registry = registry;
this.incidentDao = incidentDao;
this.historyListener = historyListener;
this.platformBus = platformBus;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public AlarmIncidentModel getCurrentIncident(SubsystemContext<AlarmSubsystemModel> context) {
String incidentAddressString = context.model().getCurrentIncident();
if (isEmpty(incidentAddressString)) {
return null;
}
Address incidentAddress = Address.fromString(incidentAddressString);
return getIncident(context, incidentAddress);
}
@Override
public AlarmIncidentModel getIncident(SubsystemContext<AlarmSubsystemModel> context, Address incidentAddress) {
return toModel(incidentDao.findById(context.getPlaceId(), (UUID) incidentAddress.getId()));
}
@Override
public List<AlarmIncidentModel> listIncidents(SubsystemContext<AlarmSubsystemModel> context) {
return toModel(incidentDao.listIncidentsByPlace(context.getPlaceId(), maxIncidents).getResults());
}
@Override
public Address addPreAlert(SubsystemContext<AlarmSubsystemModel> context, String alarm, Date prealertEndTime, List<IncidentTrigger> triggers) {
TrackerEvent event = createTrackerEvent(alarm, TrackerState.PREALERT);
AlarmIncident incident = prealert(context, alarm, prealertEndTime, event);
context.model().setCurrentIncident(incident.getAddress().getRepresentation());
return incident.getAddress();
}
@Override
public Address addAlert(SubsystemContext<AlarmSubsystemModel> context, String alarm, List<IncidentTrigger> triggers) {
return addAlert(context, alarm, triggers, true);
}
@Override
public Address addAlert(SubsystemContext<AlarmSubsystemModel> context, String alarm, List<IncidentTrigger> triggers, boolean sendNotifications) {
TrackerEvent event = createTrackerEvent(alarm, TrackerState.ALERT);
AlarmIncident incident = alert(context, alarm, event);
context.model().setCurrentIncident(incident.getAddress().getRepresentation());
onAlertAdded(context, incident, alarm, triggers, sendNotifications);
if (!triggers.isEmpty()) {
markTriggerSent(context, triggers.get(triggers.size() - 1));
}
return incident.getAddress();
}
protected void markTriggerSent(SubsystemContext<AlarmSubsystemModel> context, IncidentTrigger trigger) {
if (trigger != null) {
context.setVariable(VAR_TRIGGER_SENT, trigger.getTime());
}
}
@Override
public void updateIncident(SubsystemContext<AlarmSubsystemModel> context, List<IncidentTrigger> triggers) {
updateIncident(context, triggers, true);
}
@Override
public void updateIncident(SubsystemContext<AlarmSubsystemModel> context, List<IncidentTrigger> triggers, boolean sendNotifications) {
if (triggers.isEmpty()) {
// the triggers have just been cleared, ignore
return;
}
AlarmIncident incident = incidentDao.current(context.getPlaceId());
if (incident == null) {
context.logger().warn("Unable to udpate incident for place [{}], no current incident", context.getPlaceId());
return;
}
issueAlertUpdatedIfNeeded(context, incident, triggers, sendNotifications);
historyListener.onTriggersAdded(context, incident.getAddress(), triggers);
}
@Override
public void updateIncidentHistory(SubsystemContext<AlarmSubsystemModel> context, List<IncidentTrigger> events) {
if (events.isEmpty()) {
return;
}
AlarmIncident incident = incidentDao.current(context.getPlaceId());
if (incident == null) {
return;
}
historyListener.onTriggersAdded(context, incident.getAddress(), events);
}
@Override
public void onHubConnectivityChanged(SubsystemContext<AlarmSubsystemModel> context, Model hub) {
context.logger().debug("Hub connectivity changed to [{}]", HubConnectionModel.getState(hub));
AlarmIncident incident = incidentDao.current(context.getPlaceId());
if (incident == null) {
return;
}
historyListener.onHubConnectivityChanged(context, incident.getAddress());
}
/**
* Sends information about additional alarms if there has been an update since the initial alert was sent.
* This prevents the same trigger from being sent in addAlert / updateIncident
* This is a bit tricky to get right because most alarms will send this information when the replacedociated alert is first
* tripped. However security alarms hold onto the triggers and don't send them until the entrance grace period expires, or
* the alarm is confirmed.
* @param context
* @param triggers
*/
protected void issueAlertUpdatedIfNeeded(SubsystemContext<AlarmSubsystemModel> context, AlarmIncident incident, List<IncidentTrigger> triggers, boolean sendNotifications) {
IncidentTrigger firstTrigger = triggers.get(0);
String alarm = firstTrigger.getAlarm();
if (AlarmModel.isAlertStateALERT(alarm, context.model())) {
// don't fire a trigger that was just sent by addAlert
Date lastTrigger = context.getVariable(VAR_TRIGGER_SENT).as(Date.clreplaced);
if (lastTrigger == null || lastTrigger.before(firstTrigger.getTime())) {
onAlertUpdated(context, incident, alarm, triggers, sendNotifications);
}
// clear it out once its been processed
if (lastTrigger != null) {
context.setVariable(VAR_TRIGGER_SENT, null);
}
}
}
@Override
public Date verify(SubsystemContext<AlarmSubsystemModel> context, Address incidentAddress, Address verifiedBy) throws ErrorEventException {
AlarmIncident incident = incidentDao.findById(context.getPlaceId(), (UUID) incidentAddress.getId());
Errors.replacedertFound(incident, incidentAddress);
Errors.replacedertValidRequest(incident.getAlertState() != AlertState.COMPLETE, "Can't verify a completed incident");
context.logger().debug("Incident [{}] was verified by [{}]", incidentAddress, verifiedBy);
return onIncidentVerified(context, incident, verifiedBy);
}
@Override
public AlarmIncidentModel cancel(SubsystemContext<AlarmSubsystemModel> context, final Address cancelledBy, String method) {
AlarmIncident incident = incidentDao.current(context.getPlaceId());
if (incident == null) {
// no current incident, clear it out
if (StringUtils.isEmpty(context.model().getCurrentIncident())) {
context.logger().warn("Subsystem attempting to clear non-existent incident");
return null;
}
Address ia = Address.fromString(context.model().getCurrentIncident());
incident = incidentDao.findById(context.getPlaceId(), (UUID) ia.getId());
if (incident == null) {
context.logger().warn("Subsystem attempting to cancel non-existent incident [{}] -- repairing state", context.model().getCurrentIncident());
registry.loadByPlace(context.getPlaceId()).ifPresent((executor) -> executor.onPlatformMessage(createCompletedEvent(context.getPlaceId(), ia, cancelledBy)));
return null;
}
context.logger().warn("Subsystem attempting to cancel completed incident [{}] -- repairing state", context.model().getCurrentIncident());
incident = onCompleted(incident, cancelledBy);
return toModel(incident);
} else {
return cancel(context, incident, cancelledBy, method);
}
}
@Override
public AlarmIncidentModel cancel(SubsystemContext<AlarmSubsystemModel> context, @NonNull String incidentAddress, @Nullable Address cancelledBy, String method) {
final Address ia = Address.fromString(incidentAddress);
AlarmIncident incident = incidentDao.findById(context.getPlaceId(), (UUID) ia.getId());
if (incident == null) {
context.logger().warn("Subsystem attempting to cancel non-existent incident [{}] -- repairing state", context.model().getCurrentIncident());
registry.loadByPlace(context.getPlaceId()).ifPresent((executor) -> executor.onPlatformMessage(createCompletedEvent(context.getPlaceId(), ia, cancelledBy)));
return null;
} else {
return cancel(context, incident, cancelledBy, method);
}
}
protected AlarmIncidentModel cancel(SubsystemContext<AlarmSubsystemModel> context, AlarmIncident incident, Address cancelledBy, String method) {
if (incident.getAlertState() == AlertState.PREALERT || incident.getAlertState() == AlertState.ALERT) {
AlarmIncident updated = AlarmIncident.builder(incident).withAlertState(AlertState.CANCELLING).build();
save(incident, updated);
historyListener.onCancelled(context, incident, cancelledBy, method);
incident = updated;
}
if (incident.getHubAlertState() == AlertState.CANCELLING || incident.getHubAlertState() == AlertState.COMPLETE) {
Model hub = AlarmUtil.getHubModel(context, false);
if (HubAlarmModel.getCurrentIncident(hub, "").isEmpty()) {
if (incident.getPlatformAlertState() == AlertState.COMPLETE) {
context.logger().debug("Hub incident has completed and platform was already complete, incident [{}] can complete", incident.getAddress());
AlarmIncident completed = onCompleted(incident, cancelledBy);
return toModel(completed);
} else if (incident.getHubAlertState() == AlertState.CANCELLING) {
context.logger().debug("Hub incident has completed, but platform is still pending");
AlarmIncident updated = AlarmIncident.builder(incident).withHubAlertState(AlertState.COMPLETE).build();
save(incident, updated);
incident = updated;
// drop through to doCancel logic below
} else {
context.logger().debug("Hub is clear, but platform is still pending");
// drop through to doCancel logic below
}
}
}
if (incident.getPlatformAlertState() == AlertState.COMPLETE) {
context.logger().debug("Waiting for hub alert to complete, platform already cleared");
} else {
ListenableFuture<Void> future = doCancel(context, incident, cancelledBy, method);
final UUID placeId = context.getPlaceId();
final Address incidentAddress = incident.getAddress();
Futures.addCallback(future, new FutureCallback<Void>() {
@Override
public void onSuccess(Void result) {
onPlatformCompleted(placeId, (UUID) incidentAddress.getId(), cancelledBy);
}
@Override
public void onFailure(Throwable t) {
/* no op */
logger.debug("Failed to cancel incident [{}]", incidentAddress, t);
}
}, MoreExecutors.directExecutor());
}
return toModel(incident);
}
@Nullable
protected AlarmIncident current(UUID placeId) {
return incidentDao.current(placeId);
}
/**
* Used when attempting to get the active alert in order
* to add more triggers to it.
* @param context
* @return
*/
@Nullable
protected AlarmIncident getActiveIncident(SubsystemContext<AlarmSubsystemModel> context) {
return current(context.getPlaceId());
}
protected AlarmIncident.Builder buildIncident(SubsystemContext<AlarmSubsystemModel> context) {
return AlarmIncident.builder().withId(IrisUUID.timeUUID()).withPlaceId(context.getPlaceId()).withMonitoringState(MonitoringState.NONE);
}
protected void onIncidentUpdated(UUID placeId, Address incidentAddress, MessageBody message) {
AlarmIncident incident = incidentDao.findById(placeId, (UUID) incidentAddress.getId());
Errors.replacedertFound(incident, incidentAddress);
String state = AlarmIncidentCapability.getMonitoringState(message);
Errors.replacedertValidRequest(state != null, "Must specify a monitoring state");
MonitoringState monitoringState;
try {
monitoringState = AlarmIncident.MonitoringState.valueOf(state);
} catch (IllegalArgumentException e) {
logger.warn("Unrecognized monitoring state [{}] -- ignoring tracker update for incident [{}]", state, incidentAddress);
throw new ErrorEventException(Errors.invalidParam(AlarmIncidentCapability.ATTR_MONITORINGSTATE));
}
MonitoringState oldState = incident.getMonitoringState();
AlarmIncident.Builder builder = AlarmIncident.builder(incident).withMonitoringState(monitoringState);
TrackerState trackerState = monitoringState.getTrackerState(oldState);
if (trackerState != null) {
String customTrackerMessage = null;
List<Map<String, Object>> trackerMap = AlarmIncidentCapability.getTracker(message);
if (trackerMap != null && !trackerMap.isEmpty()) {
TrackerEvent customTracker = new TrackerEvent(trackerMap.get(0));
customTrackerMessage = customTracker.getMessage();
}
TrackerEvent event = createTrackerEvent(incident.getAlert().name(), trackerState, customTrackerMessage);
builder.addTrackerEvent(event);
}
AlarmIncident updated = builder.build();
save(incident, updated);
}
@Nullable
protected Date onIncidentVerified(SubsystemContext<AlarmSubsystemModel> context, AlarmIncident incident, Address verifiedBy) {
if (!incident.isConfirmed()) {
AlarmIncident.Builder builder = AlarmIncident.builder(incident).withConfirmed(true);
AlarmIncident updated = builder.build();
save(incident, updated);
return new Date();
} else {
return null;
}
}
@Nullable
protected AlarmIncident onPlatformCompleted(UUID placeId, UUID incidentId, Address cancelledBy) {
AlarmIncident incident = incidentDao.findById(placeId, incidentId);
if (incident == null) {
logger.warn("Incident cancellation succeeded, but incident could not be found [{}]", incidentId);
return null;
} else if (incident.getHubAlertState() == null || incident.getHubAlertState() == AlertState.COMPLETE) {
// fully complete
return onCompleted(incident, cancelledBy);
} else {
logger.debug("Incident [{}] is platform complete, waiting on hub to fully clear", incidentId);
MonitoringState monitoringState = null;
switch(incident.getMonitoringState()) {
case PENDING:
case DISPATCHING:
// cancelled before dispatch
monitoringState = MonitoringState.CANCELLED;
default:
monitoringState = incident.getMonitoringState();
}
AlarmIncident updated = AlarmIncident.builder(incident).withPlatformAlertState(AlertState.COMPLETE).withMonitoringState(monitoringState).withCancelledBy(cancelledBy).build();
save(incident, updated);
return updated;
}
}
protected AlarmIncident onCompleted(AlarmIncident incident, Address cancelledBy) {
TrackerEvent event = createTrackerEvent(incident.getAlert().name(), TrackerState.CANCELLED);
MonitoringState monitoringState = null;
switch(incident.getMonitoringState()) {
case PENDING:
case DISPATCHING:
// cancelled before dispatch
monitoringState = MonitoringState.CANCELLED;
default:
monitoringState = incident.getMonitoringState();
}
AlarmIncident cancelled = AlarmIncident.builder(incident).withAlertState(AlertState.COMPLETE).withMonitoringState(monitoringState).withCancelledBy(cancelledBy).withEndTime(new Date()).addTrackerEvent(event).build();
save(incident, cancelled);
platformBus.send(createCompletedEvent(incident.getPlaceId(), incident.getAddress(), cancelledBy));
return cancelled;
}
protected abstract ListenableFuture<Void> doCancel(SubsystemContext<AlarmSubsystemModel> context, AlarmIncident incident, Address cancelledBy, String method);
protected AlarmIncident prealert(SubsystemContext<AlarmSubsystemModel> context, String alarm, Date prealertEndTime, TrackerEvent event) {
AlarmIncident current = getActiveIncident(context);
if (current != null) {
return current;
}
AlarmIncident.Builder builder = buildIncident(context).withAlertState(AlertState.PREALERT).withPrealertEndTime(prealertEndTime).withMonitored(determineMonitoredFlag(context, alarm, current)).addAlarm(alarm).addTrackerEvent(event);
AlarmIncident updated = builder.build();
save(current, updated);
return updated;
}
protected AlarmIncident alert(SubsystemContext<AlarmSubsystemModel> context, String alarm, TrackerEvent event) {
AlarmIncident current = getActiveIncident(context);
AlarmIncident.Builder builder;
if (current == null) {
builder = buildIncident(context).withAlertState(AlertState.ALERT).withMonitoringState(MonitoringState.NONE).addTrackerEvent(event);
} else {
builder = AlarmIncident.builder(current);
// don't add multiple alert tracker events
if (current.getAlertState() != AlertState.ALERT) {
builder.withAlertState(AlertState.ALERT).addTrackerEvent(event);
} else // if the alarm was verified during prealert then the
// hub alert state won't transition until it reports
// although platformState / alertState will already be ALERT
if (current.getHubAlertState() == AlertState.PREALERT) {
builder.withHubAlertState(AlertState.ALERT);
}
}
builder.addAlarm(alarm).withMonitored(determineMonitoredFlag(context, alarm, current));
AlarmIncident updated = builder.build();
save(current, updated);
return updated;
}
protected void save(AlarmIncident current, AlarmIncident updated) {
incidentDao.upsert(updated);
MessageBody event;
if (current == null) {
event = MessageBody.buildMessage(Capability.EVENT_ADDED, updated.asMap());
} else {
event = MessageBody.buildMessage(Capability.EVENT_VALUE_CHANGE, updated.diff(current));
}
PlatformMessage message = PlatformMessage.broadcast().from(updated.getAddress()).withPlaceId(updated.getPlaceId()).withPopulation(populationCacheMgr.getPopulationByPlaceId(updated.getPlaceId())).withPayload(event).create();
platformBus.send(message);
}
protected void onAlertAdded(SubsystemContext<?> context, AlarmIncident incident, String alarm, List<IncidentTrigger> events, boolean sendNotifications) {
try {
// wds - this log message drives geo reports in the log system.
logger.info("Alert added of type [{}] for incident [{}].", alarm, incident.getId());
List<Map<String, Object>> triggers = IrisCollections.transform(events, IncidentTrigger::toMap);
MessageBody payload = MessageBody.messageBuilder(AlarmIncident.toEvent(AlertType.valueOf(alarm))).withAttribute(AlarmIncidentCapability.COAlertEvent.ATTR_TRIGGERS, triggers).create();
PlatformMessage message = PlatformMessage.builder().from(incident.getAddress()).broadcast().withPlaceId(context.getPlaceId()).withPopulation(context.getPopulation()).withActor(context.model().getAddress()).withPayload(payload).create();
platformBus.send(message);
} catch (Exception e) {
context.logger().warn("Unable to determine alert type for {}", alarm, e);
}
}
protected void onAlertUpdated(SubsystemContext<?> context, AlarmIncident incident, String alarm, List<IncidentTrigger> events, boolean sendNotifications) {
// no-op
}
protected boolean determineMonitoredFlag(SubsystemContext<AlarmSubsystemModel> context, String alarm, AlarmIncident current) {
if (SubsystemUtils.isProMon(context)) {
Set<AlertType> allAlarms = new HashSet<AlertType>();
if (current != null) {
if (current.getAdditionalAlerts() != null) {
allAlarms.addAll(current.getAdditionalAlerts());
}
if (current.getAlert() != null) {
allAlarms.add(current.getAlert());
}
}
allAlarms.add(AlertType.valueOf(alarm));
if (!Sets.filter(allAlarms, isMonitoredPredicate).isEmpty()) {
// at least one monitored alert type
return true;
}
}
return false;
}
protected List<String> allAlarms(AlarmIncident incident) {
ImmutableList.Builder<String> alarms = ImmutableList.builder();
alarms.add(incident.getAlert().name());
alarms.addAll(incident.getAdditionalAlerts().stream().map(AlertType::name).collect(Collectors.toList()));
return alarms.build();
}
protected PlatformMessage createCompletedEvent(UUID placeId, Address incidentAddress, Address cancelledBy) {
return PlatformMessage.broadcast().from(incidentAddress).withPlaceId(placeId).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeId)).withActor(cancelledBy).withPayload(AlarmIncidentCapability.CompletedEvent.instance()).create();
}
protected static TrackerEvent createTrackerEvent(String alarm, TrackerState state) {
return createTrackerEvent(alarm, state, null);
}
protected static TrackerEvent createTrackerEvent(String alarm, TrackerState state, String customMessage) {
TrackerEvent event = new TrackerEvent();
event.setTime(new Date());
event.setState(state.name());
event.setKey(alarm.toLowerCase() + "." + state.name().toLowerCase());
event.setMessage(StringUtils.isBlank(customMessage) ? messages.get(event.getKey()) : customMessage);
return event;
}
public static AlarmIncidentModel toModel(AlarmIncident incident) {
Map<String, Object> attributes = incident.asMap();
return new AlarmIncidentModel(new SimpleModel(attributes));
}
public static List<AlarmIncidentModel> toModel(List<AlarmIncident> incidents) {
return incidents.stream().map(PlatformAlarmIncidentService::toModel).collect(Collectors.toList());
}
public static String getEventMessage(String key) {
return messages.get(key);
}
}
16
Source : RuleService.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
/**
*/
@Singleton
public clreplaced RuleService extends AbstractPlatformMessageListener implements ParreplacedionListener {
public static final String PROP_THREADPOOL = "service.rule.threadpool";
private static final Logger logger = LoggerFactory.getLogger(RuleService.clreplaced);
private final Timer parreplacedionLoadTimer;
private final RuleEnvironmentDao ruleDao;
private final PlatformMessageBus platformBus;
private final Parreplacedioner parreplacedioner;
private final RuleDao ruleDefDao;
private final ModelDao modelDao;
private final PlaceDAO placeDao;
private final RuleCatalogLoader catalogs;
private final PlaceExecutorRegistry registry;
private final ListHistoryEntriesHandler listHistoryEntries;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public RuleService(@Named(PROP_THREADPOOL) Executor executor, RuleEnvironmentDao ruleDao, PlatformMessageBus platformBus, Parreplacedioner parreplacedioner, RuleDao ruleDefDao, ModelDao modelDao, PlaceDAO placeDao, RuleCatalogLoader catalogs, PlaceExecutorRegistry environments, ListHistoryEntriesHandler listHistoryEntries, PlacePopulationCacheManager populationCacheMgr) {
super(platformBus, executor);
this.parreplacedionLoadTimer = IrisMetrics.metrics("service.rules").timer("parreplacedionloadtime");
this.ruleDao = ruleDao;
this.platformBus = platformBus;
this.parreplacedioner = parreplacedioner;
this.ruleDefDao = ruleDefDao;
this.modelDao = modelDao;
this.placeDao = placeDao;
this.catalogs = catalogs;
this.registry = environments;
this.listHistoryEntries = listHistoryEntries;
this.populationCacheMgr = populationCacheMgr;
}
@Override
protected void onStart() {
parreplacedioner.addParreplacedionListener(this);
// then start listening
listen();
}
protected void listen() {
addListeners(AddressMatchers.equals(Address.broadcastAddress()), AddressMatchers.platformService(MessageConstants.SERVICE, PlatformConstants.SERVICE_RULE), AddressMatchers.platformService(MessageConstants.SERVICE, PlatformConstants.SERVICE_RULE_TMPL));
}
@Override
public void onParreplacedionsChanged(ParreplacedionChangedEvent event) {
logger.info("Loading rules for [{}] parreplacedions...", event.getParreplacedions().size());
registry.clear();
for (PlatformParreplacedion parreplacedion : event.getParreplacedions()) {
executor().execute(() -> loadRulesByParreplacedion(parreplacedion));
}
}
@Override
protected void handleEvent(PlatformMessage message) {
if (Capability.EVENT_DELETED.equals(message.getMessageType())) {
Address source = message.getSource();
if (source instanceof PlatformServiceAddress && PlatformConstants.SERVICE_PLACES.equals(source.getGroup())) {
onPlaceDeleted((UUID) source.getId());
return;
}
}
UUID placeId = getPlaceId(message);
if (placeId == null) {
return;
}
PlaceEnvironmentExecutor executor = registry.getExecutor(placeId).orNull();
if (executor == null) {
return;
}
executor.onMessageReceived(message);
}
private void onPlaceDeleted(UUID placeId) {
// remove the executor and stop its execution
registry.stop(placeId);
// remove all rules, scenes and actions for the place
ruleDao.deleteByPlace(placeId);
}
@Override
protected void handleRequestAndSendResponse(PlatformMessage message) {
// many rule service responses are handled in the rule service handler, which
// will send a response itself, so allow null response here
getMessageBus().invokeAndSendIfNotNull(message, () -> Optional.ofNullable(handleRequest(message)));
}
@Override
protected MessageBody handleRequest(PlatformMessage message) throws Exception {
UUID placeId = message.getPlaceId() == null ? null : UUID.fromString(message.getPlaceId());
Address destination = message.getDestination();
// dispatch to the specific rule -- move more in here
if (RuleCapability.EnableRequest.NAME.equals(message.getMessageType()) || RuleCapability.DisableRequest.NAME.equals(message.getMessageType())) {
PlaceEnvironmentExecutor executor = registry.getExecutor(placeId).orNull();
if (executor == null) {
return Errors.notFound(message.getDestination());
}
executor.handleRequest(message);
return null;
}
// rule service requests
if (com.iris.messages.service.RuleService.ListRuleTemplatesRequest.NAME.equals(message.getMessageType())) {
return handleListRuleTemplates(message.getValue());
}
if (com.iris.messages.service.RuleService.ListRulesRequest.NAME.equals(message.getMessageType())) {
return handleListRules(message.getValue());
}
if (com.iris.messages.service.RuleService.GetCategoriesRequest.NAME.equals(message.getMessageType())) {
return handleGetCategories(message.getValue());
}
if (com.iris.messages.service.RuleService.GetRuleTemplatesByCategoryRequest.NAME.equals(message.getMessageType())) {
return handleGetRuleTemplatesByCategory(message.getValue());
}
// rule template requests
if (RuleTemplateCapability.ResolveRequest.NAME.equals(message.getMessageType())) {
MessageBody body = message.getValue();
replacedertPlaceMatches(placeId, destination, body);
return handleResolve(message.getDestination().getId(), body);
}
if (RuleTemplateCapability.CreateRuleRequest.NAME.equals(message.getMessageType())) {
MessageBody body = message.getValue();
replacedertPlaceMatches(placeId, destination, body);
return handleCreateRule(message.getDestination(), message.getDestination().getId(), body);
}
if (com.iris.messages.service.RuleService.ListRulesRequest.NAME.equals(message.getMessageType())) {
MessageBody body = message.getValue();
replacedertPlaceMatches(placeId, destination, body);
return handleListRules(message.getValue());
}
// rule requests
if (RuleCapability.DeleteRequest.NAME.equals(message.getMessageType())) {
return handleDeleteRule(placeId, message.getDestination(), message.getValue());
}
if (RuleCapability.UpdateContextRequest.NAME.equals(message.getMessageType())) {
return handleUpdateRuleContext(placeId, message.getDestination(), message.getValue());
}
if (RuleCapability.ListHistoryEntriesRequest.NAME.equals(message.getMessageType())) {
return handleListHistoryEntries(message.getDestination(), message);
}
// base requests -- could be rule or template
if (Capability.CMD_GET_ATTRIBUTES.equals(message.getMessageType())) {
return handleGetAttributes(message.getDestination(), message.getValue(), message.getPlaceId());
}
if (Capability.CMD_SET_ATTRIBUTES.equals(message.getMessageType())) {
return handleSetAttributes(placeId, message.getDestination(), message.getValue());
}
return super.handleRequest(message);
}
protected void loadRulesByParreplacedion(PlatformParreplacedion parreplacedion) {
try (Timer.Context context = parreplacedionLoadTimer.time()) {
placeDao.streamByParreplacedionId(parreplacedion.getId()).forEach((place) -> registry.start(place.getId()));
}
}
// TODO optimize this
private UUID getPlaceId(PlatformMessage message) {
String placeId = message.getPlaceId();
return placeId == null ? null : UUID.fromString(placeId);
}
private UUID getPlaceId(MessageBody body) {
if (body.getAttributes().get(com.iris.messages.service.RuleService.ListRuleTemplatesRequest.ATTR_PLACEID) != null) {
return UUID.fromString((String) body.getAttributes().get(com.iris.messages.service.RuleService.ListRuleTemplatesRequest.ATTR_PLACEID));
}
return null;
}
// FIXME this results in a lot of duplicated checks -- should consolidate this logic in future revisions
private void replacedertPlaceMatches(UUID placeId, Address destination, MessageBody body) {
if (placeId == null) {
return;
}
if (!Objects.equals(placeId, getPlaceId(body))) {
throw new UnauthorizedRequestException(destination, "Unauthorized access to " + destination);
}
}
private MessageBody handleListRuleTemplates(MessageBody body) {
UUID placeId = getPlaceId(body);
// TODO: replace with better error events
Preconditions.checkNotNull(placeId, "The place ID is required");
RuleCatalog catalog = getRuleCatalogForPlace(placeId);
List<RuleTemplate> templates = catalog.getTemplates();
RuleContext context = createSimpleRuleContext(placeId);
return com.iris.messages.service.RuleService.ListRuleTemplatesResponse.builder().withRuleTemplates(templates.stream().map((rt) -> templateToMap(rt, context)).collect(Collectors.toList())).build();
}
private Map<String, Object> templateToMap(RuleTemplate template, RuleContext ruleContext) {
Map<String, Object> asMap = new HashMap<>();
asMap.put(Capability.ATTR_ADDRESS, MessageConstants.SERVICE + ":" + RuleTemplateCapability.NAMESPACE + ":" + template.getId());
asMap.put(Capability.ATTR_CAPS, ImmutableSet.of(Capability.NAMESPACE, RuleTemplateCapability.NAMESPACE));
asMap.put(Capability.ATTR_ID, template.getId());
asMap.put(Capability.ATTR_TAGS, template.getTags());
asMap.put(Capability.ATTR_TYPE, RuleTemplateCapability.NAMESPACE);
asMap.put(RuleTemplateCapability.ATTR_ADDED, template.getCreated());
asMap.put(RuleTemplateCapability.ATTR_KEYWORDS, template.getKeywords());
asMap.put(RuleTemplateCapability.ATTR_LASTMODIFIED, template.getModified());
asMap.put(RuleTemplateCapability.ATTR_TEMPLATE, template.getTemplate());
asMap.put(RuleTemplateCapability.ATTR_SATISFIABLE, ruleContext != null && template.isSatisfiable(ruleContext));
asMap.put(RuleTemplateCapability.ATTR_NAME, template.getName());
asMap.put(RuleTemplateCapability.ATTR_DESCRIPTION, template.getDescription());
asMap.put(RuleTemplateCapability.ATTR_CATEGORIES, template.getCategories());
asMap.put(RuleTemplateCapability.ATTR_PREMIUM, template.isPremium());
asMap.put(RuleTemplateCapability.ATTR_EXTRA, template.getExtra());
return asMap;
}
private MessageBody handleListRules(MessageBody body) {
UUID placeId = getPlaceId(body);
// TODO: replace with better error events
Preconditions.checkNotNull(placeId, "The place ID is required");
List<RuleDefinition> definitions = ruleDefDao.listByPlace(placeId);
return com.iris.messages.service.RuleService.ListRulesResponse.builder().withRules(definitions.stream().map((r) -> ruleToMap(r)).collect(Collectors.toList())).build();
}
private Map<String, Object> ruleToMap(RuleDefinition rd) {
Map<String, Object> asMap = new HashMap<>();
asMap.put(Capability.ATTR_ID, rd.getId().getRepresentation());
asMap.put(Capability.ATTR_ADDRESS, Address.platformService(rd.getId().getRepresentation(), RuleCapability.NAMESPACE).getRepresentation());
asMap.put(Capability.ATTR_TYPE, RuleCapability.NAMESPACE);
asMap.put(Capability.ATTR_CAPS, ImmutableSet.of(Capability.NAMESPACE, RuleCapability.NAMESPACE));
asMap.put(RuleCapability.ATTR_CREATED, rd.getCreated());
asMap.put(RuleCapability.ATTR_MODIFIED, rd.getModified());
asMap.put(RuleCapability.ATTR_NAME, rd.getName());
asMap.put(RuleCapability.ATTR_STATE, rd.isDisabled() ? RuleCapability.STATE_DISABLED : RuleCapability.STATE_ENABLED);
asMap.put(RuleCapability.ATTR_DESCRIPTION, rd.getDescription());
asMap.put(RuleCapability.ATTR_TEMPLATE, rd.getRuleTemplate());
asMap.put(RuleCapability.ATTR_CONTEXT, rd.getVariables());
return asMap;
}
private MessageBody handleGetCategories(MessageBody body) {
UUID placeId = getPlaceId(body);
// TODO: replace with better error events
Preconditions.checkNotNull(placeId, "The place ID is required");
RuleCatalog catalog = getRuleCatalogForPlace(placeId);
return com.iris.messages.service.RuleService.GetCategoriesResponse.builder().withCategories(catalog.getRuleCountByCategory()).build();
}
private MessageBody handleGetRuleTemplatesByCategory(MessageBody body) {
UUID placeId = getPlaceId(body);
String category = com.iris.messages.service.RuleService.GetRuleTemplatesByCategoryRequest.getCategory(body);
// TODO: replace with better error events
Preconditions.checkNotNull(placeId, "The place ID is required");
Preconditions.checkNotNull(category, "The category is required");
RuleCatalog catalog = getRuleCatalogForPlace(placeId);
RuleContext context = createSimpleRuleContext(placeId);
List<RuleTemplate> templates = catalog.getTemplatesForCategory(category);
return com.iris.messages.service.RuleService.GetRuleTemplatesByCategoryResponse.builder().withRuleTemplates(templates.stream().map((t) -> templateToMap(t, context)).collect(Collectors.toList())).build();
}
private MessageBody handleResolve(Object templateId, MessageBody body) {
// TODO: replace with better error events
Preconditions.checkNotNull(templateId, "The template ID is required from the destination address");
UUID placeId = getPlaceId(body);
// TODO: replace with better error events
Preconditions.checkNotNull(placeId, "The place ID is required");
RuleCatalog catalog = getRuleCatalogForPlace(placeId);
RuleTemplate template = catalog.getById((String) templateId);
// TODO: replace with better error events
Preconditions.checkNotNull(template, "No template could be found with " + templateId);
RuleContext context = createSimpleRuleContext(placeId);
Map<String, Selector> resolution = template.resolve(context);
Map<String, Map<String, Object>> transformed = new HashMap<>();
resolution.entrySet().forEach((e) -> {
transformed.put(e.getKey(), selectorToMap(e.getValue()));
});
return RuleTemplateCapability.ResolveResponse.builder().withSelectors(transformed).build();
}
private RuleContext createSimpleRuleContext(UUID placeId) {
PlaceEnvironmentExecutor executor = registry.getExecutor(placeId).orNull();
Collection<Model> models = executor != null ? executor.getModelStore().getModels() : modelDao.loadModelsByPlace(placeId, RuleModelStore.TRACKED_TYPES);
// use a simple context just for resolving
SimpleContext context = new SimpleContext(placeId, Address.platformService("rule"), LoggerFactory.getLogger("rules." + placeId));
models.stream().filter((m) -> m != null).forEach((m) -> context.putModel(m));
return context;
}
private Map<String, Object> selectorToMap(Selector selector) {
Map<String, Object> asMap = new HashMap<>();
asMap.put("type", selector.getType());
if (selector instanceof ListSelector) {
ListSelector optionSelector = (ListSelector) selector;
List<List> options = new ArrayList<>();
optionSelector.getOptions().forEach((o) -> {
options.add(Arrays.asList(o.getLabel(), o.getValue()));
});
asMap.put("options", options);
}
return asMap;
}
private MessageBody handleCreateRule(Address destination, Object templateId, MessageBody message) {
Errors.replacedertRequiredParam(templateId, "templateId");
UUID placeId = getPlaceId(message);
String name = RuleTemplateCapability.CreateRuleRequest.getName(message);
String description = RuleTemplateCapability.CreateRuleRequest.getDescription(message);
Errors.replacedertRequiredParam(placeId, "placeId");
Errors.replacedertRequiredParam(name, CreateRuleRequest.ATTR_NAME);
RuleCatalog catalog = getRuleCatalogForPlace(placeId);
RuleTemplate template = catalog.getById((String) templateId);
if (templateId == null) {
throw new ErrorEventException(Errors.notFound(Address.platformService(templateId, RuleTemplateCapability.NAMESPACE)));
}
Map<String, Object> variables = RuleTemplateCapability.CreateRuleRequest.getContext(message);
PlaceEnvironmentExecutor executor = registry.getExecutor(placeId).orNull();
if (executor == null) {
return Errors.notFound(destination);
}
try {
Callable<RuleDefinition> save = () -> doCreateRule(placeId, template, name, description, variables);
com.google.common.base.Optional<PlaceEnvironmentExecutor> executorRef = registry.getExecutor(placeId);
RuleDefinition rule;
if (executorRef.isPresent()) {
rule = executorRef.get().submit(save).get();
} else {
rule = save.call();
registry.reload(placeId);
}
return RuleTemplateCapability.CreateRuleResponse.builder().withAddress(rule.getAddress()).build();
} catch (Exception e) {
logger.warn("Error creating a new rule for place [{}] for template [{}] using variables [{}]", placeId, templateId, variables, e);
return Errors.fromException(e);
}
}
// NOTE this must run in the executor thread
private RuleDefinition doCreateRule(UUID placeId, RuleTemplate template, String name, String description, Map<String, Object> variables) throws ValidationException {
RuleDefinition rd = template.create(placeId, name, variables);
if (StringUtils.isEmpty(description)) {
rd.setDescription(template.getDescription());
} else {
rd.setDescription(description);
}
ruleDefDao.save(rd);
registry.reload(placeId);
Map<String, Object> ruleDefAsMap = ruleToMap(rd);
MessageBody added = MessageBody.buildMessage(Capability.EVENT_ADDED, ruleDefAsMap);
PlatformMessage msg = PlatformMessage.buildBroadcast(added, Address.platformService(placeId + "." + rd.getSequenceId(), PlatformConstants.SERVICE_RULE)).withPlaceId(rd.getPlaceId()).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeId)).create();
platformBus.send(msg);
return rd;
}
private MessageBody handleDeleteRule(UUID placeId, Address ruleAddress, MessageBody message) {
PlaceEnvironmentExecutor executor = registry.getExecutor(placeId).orNull();
if (executor == null) {
logger.debug("Received delete for rule at empty place [{}]", ruleAddress);
return RuleCapability.DeleteRequest.instance();
}
try {
executor.submit(() -> doDelete(ruleAddress)).get();
return RuleCapability.DeleteResponse.instance();
} catch (Exception e) {
logger.warn("Error deleting rule [{}]", ruleAddress, e);
return Errors.fromException(e);
}
}
// NOTE this must run in the executor thread
private void doDelete(Address ruleAddress) {
RuleDefinition rd = loadRuleDefintion((PlatformServiceAddress) ruleAddress);
if (rd != null) {
ruleDefDao.delete(rd.getPlaceId(), rd.getSequenceId());
PlatformMessage msg = PlatformMessage.builder().broadcast().from(Address.platformService(rd.getPlaceId(), PlatformConstants.SERVICE_RULE, rd.getSequenceId())).withPlaceId(rd.getPlaceId()).withPopulation(populationCacheMgr.getPopulationByPlaceId(rd.getPlaceId())).withPayload(Capability.EVENT_DELETED).create();
platformBus.send(msg);
registry.reload(rd.getPlaceId());
}
}
private MessageBody handleGetAttributes(Address ruleAddress, MessageBody message, String placeId) {
Errors.replacedertRequiredParam(placeId, "placeId");
PlatformServiceAddress addr = (PlatformServiceAddress) ruleAddress;
Collection<String> nameColl = (Collection<String>) message.getAttributes().get("names");
Set<String> names = nameColl == null ? Collections.<String>emptySet() : new HashSet<String>(nameColl);
Map<String, Object> attrs = new HashMap<>();
if (addr.getGroup().equals(PlatformConstants.SERVICE_RULE_TMPL)) {
RuleCatalog catalog = getRuleCatalogForPlace(UUID.fromString(placeId));
RuleTemplate rt = catalog.getById((String) addr.getId());
// TODO: better error event
Preconditions.checkNotNull(rt, "No rule template can be found for " + addr.getId());
// TODO: without the place, we cannot determine satisfiability either
attrs = templateToMap(rt, null);
} else if (addr.getGroup().equals(PlatformConstants.SERVICE_RULE)) {
RuleDefinition ruleDef = loadRuleDefintion(addr);
// TODO: better error event
Preconditions.checkNotNull(ruleDef, "No rule could be found for " + addr.getRepresentation());
attrs = ruleToMap(ruleDef);
}
return MessageBody.buildMessage(Capability.EVENT_GET_ATTRIBUTES_RESPONSE, filter(attrs, names));
}
private Map<String, Object> filter(Map<String, Object> attrs, Set<String> caps) {
if (caps == null || caps.isEmpty()) {
return attrs;
}
return attrs.entrySet().stream().filter((e) -> {
return caps.contains(e.getKey()) || caps.contains(e.getKey().split(":")[0]);
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
private MessageBody handleSetAttributes(UUID placeId, Address ruleAddress, MessageBody message) {
PlatformServiceAddress addr = (PlatformServiceAddress) ruleAddress;
if (addr.getGroup().equals(PlatformConstants.SERVICE_RULE_TMPL)) {
return ErrorEvent.fromCode("error.attribute.not_writable", "Rule templates do not have any writable attributes");
}
PlaceEnvironmentExecutor executor = registry.getExecutor(placeId).orNull();
if (executor == null) {
return Errors.notFound(ruleAddress);
}
Set<String> readOnlyKeys = message.getAttributes().keySet().stream().filter((k) -> {
return !RuleCapability.ATTR_NAME.equals(k) && !RuleCapability.ATTR_DESCRIPTION.equals(k);
}).collect(Collectors.toSet());
if (!readOnlyKeys.isEmpty()) {
return ErrorEvent.fromCode("error.attribute.not_writable", readOnlyKeys.toString() + " are not writable attributes");
}
RuleDefinition rd = loadRuleDefintion(addr);
Map<String, Object> attributesSet = new HashMap<>();
String name = RuleCapability.getName(message);
if (name != null) {
attributesSet.put(RuleCapability.ATTR_NAME, name);
rd.setName(name);
}
String desc = RuleCapability.getDescription(message);
if (desc != null) {
attributesSet.put(RuleCapability.ATTR_DESCRIPTION, desc);
rd.setDescription(desc);
}
if (!attributesSet.isEmpty()) {
try {
executor.submit(() -> doUpdate(rd, attributesSet)).get();
} catch (Exception e) {
logger.warn("Error updating rule [{}]", ruleAddress, e);
return Errors.fromException(e);
}
}
return MessageBody.emptyMessage();
}
private MessageBody handleUpdateRuleContext(UUID placeId, Address ruleAddress, MessageBody message) {
PlaceEnvironmentExecutor executor = registry.getExecutor(placeId).orNull();
if (executor == null) {
return Errors.notFound(ruleAddress);
}
RuleDefinition rd = loadRuleDefintion((PlatformServiceAddress) ruleAddress);
if (rd == null) {
return Errors.notFound(ruleAddress);
}
Map<String, Object> variables = new HashMap<>(rd.getVariables());
Map<String, Object> newVariables = RuleCapability.UpdateContextRequest.getContext(message);
newVariables.entrySet().forEach((e) -> variables.put(e.getKey(), e.getValue()));
rd.setVariables(variables);
ImmutableMap.Builder<String, Object> changesBuilder = ImmutableMap.<String, Object>builder().put(RuleCapability.ATTR_CONTEXT, variables);
String templateName = RuleCapability.UpdateContextRequest.getTemplate(message);
if (!StringUtils.isEmpty(templateName)) {
logger.debug("Changing rule [{}] from template [{}] to template [{}]", rd.getAddress(), rd.getRuleTemplate(), templateName);
rd.setRuleTemplate(templateName);
changesBuilder.put(RuleCapability.ATTR_TEMPLATE, templateName);
}
// Need to regenerate the rule definition or it won't actually change the rule, just the definition.
RuleCatalog catalog = getRuleCatalogForPlace(rd.getPlaceId());
RuleTemplate template = catalog.getById(rd.getRuleTemplate());
// TODO: replace with better error events
Preconditions.checkNotNull(template, "No template could be found with " + rd.getRuleTemplate());
try {
final RuleDefinition toUpdate = template.regenerate(rd);
executor.submit(() -> doUpdate(toUpdate, changesBuilder.build())).get();
} catch (ValidationException ex) {
logger.error("Error editing rule for place [{}] for template [{}] using variables [{}]", rd.getPlaceId(), rd.getRuleTemplate(), variables, ex);
return Errors.fromException(ex);
} catch (Exception ex) {
logger.error("Error updating rule for [{}]", rd.getAddress(), ex);
return Errors.fromException(ex);
}
return RuleCapability.UpdateContextResponse.instance();
}
// NOTE this must run in the executor thread
private void doUpdate(RuleDefinition rd, Map<String, Object> changes) {
ruleDefDao.save(rd);
registry.reload(rd.getPlaceId());
PlatformMessage msg = PlatformMessage.broadcast().from(Address.platformService(rd.getPlaceId(), PlatformConstants.SERVICE_RULE, rd.getSequenceId())).withPlaceId(rd.getPlaceId()).withPopulation(populationCacheMgr.getPopulationByPlaceId(rd.getPlaceId())).withPayload(Capability.EVENT_VALUE_CHANGE, changes).create();
platformBus.send(msg);
}
private MessageBody handleListHistoryEntries(Address ruleAddress, PlatformMessage message) {
RuleDefinition rd = loadRuleDefintion((PlatformServiceAddress) ruleAddress);
if (rd == null) {
throw new NotFoundException(ruleAddress);
}
Errors.replacedertPlaceMatches(message, rd.getPlaceId());
return listHistoryEntries.handleRequest(rd, message);
}
private RuleDefinition loadRuleDefintion(PlatformServiceAddress ruleAddress) {
PlatformServiceAddress platformAddr = ruleAddress;
UUID placeId = (UUID) platformAddr.getId();
Integer ruleSequence = platformAddr.getContextQualifier();
return ruleDefDao.findById(placeId, ruleSequence);
}
private RuleCatalog getRuleCatalogForPlace(UUID placeId) {
return catalogs.getCatalogForPlace(placeId);
}
}
16
Source : TestAccountActivateHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@RunWith(Parameterized.clreplaced)
@Mocks({ AccountDAO.clreplaced, PlatformMessageBus.clreplaced, PersonDAO.clreplaced, PlacePopulationCacheManager.clreplaced })
public clreplaced TestAccountActivateHandler extends IrisMockTestCase {
private static final Address clientAddress = Address.clientAddress("test", "test");
@Inject
private AccountDAO accountDaoMock;
@Inject
private PersonDAO personDao;
@Inject
private PlatformMessageBus bus;
@Inject
private AccountActivateHandler handler;
private String curAccountState;
private boolean accountSaved;
private boolean notificationSent;
private boolean alwaysSucceed;
@Inject
protected PlacePopulationCacheManager mockPopulationCacheMgr;
@Parameters(name = "currentState[{0}],isAccountSaved[{1}],isNotificationSent[{2}]")
public static List<Object[]> files() {
return Arrays.<Object[]>asList(new Object[] { Account.AccountState.SIGN_UP_1, true, true, false }, new Object[] { null, true, true, false }, new Object[] { Account.AccountState.SIGN_UP_2, true, false, false }, new Object[] { Account.AccountState.COMPLETE, false, false, true });
}
public TestAccountActivateHandler(String curAccountState, boolean accountSaved, boolean notificationSent, boolean alwaysSucceed) {
this.curAccountState = curAccountState;
this.accountSaved = accountSaved;
this.notificationSent = notificationSent;
this.alwaysSucceed = alwaysSucceed;
}
@Before
public void setupMocks() {
EasyMock.expect(mockPopulationCacheMgr.getPopulationByPlaceId(EasyMock.anyObject(UUID.clreplaced))).andReturn(Population.NAME_GENERAL).anyTimes();
}
@Test
public void testMissingOwnerName() {
Person owner = createPerson();
// no first name
owner.setFirstName(null);
Account account = createAccount(curAccountState);
account.setOwner(owner.getId());
owner.setAccountId(account.getId());
EasyMock.expect(personDao.findById(owner.getId())).andReturn(owner).anyTimes();
replay();
try {
handler.handleRequest(account, createAccountActivateMessage(account));
if (!alwaysSucceed) {
fail("should fail");
}
} catch (ErrorEventException e) {
replacedertEquals(AccountActivateHandler.ERROR_INVALID_STATE, e.getCode());
}
verify();
}
@Test
public void testMissingOwner() {
Person owner = createPerson();
Account account = createAccount(curAccountState);
// account no owner
account.setOwner(null);
owner.setAccountId(account.getId());
replay();
try {
handler.handleRequest(account, createAccountActivateMessage(account));
if (!alwaysSucceed) {
fail("should fail");
}
} catch (ErrorEventException e) {
replacedertEquals(AccountActivateHandler.ERROR_INVALID_STATE, e.getCode());
}
verify();
}
@Test
public void testActivateState() {
Person owner = createPerson();
Account account = createAccount(curAccountState);
account.setOwner(owner.getId());
owner.setAccountId(account.getId());
Place place1 = createPlace(account.getId());
Place place2 = createPlace(account.getId());
account.setPlaceIDs(ImmutableSet.<UUID>of(place1.getId(), place2.getId()));
EasyMock.expect(personDao.findById(owner.getId())).andReturn(owner).anyTimes();
Capture<Account> accountCaptured = null;
if (accountSaved) {
accountCaptured = Capture.newInstance();
EasyMock.expect(accountDaoMock.save(EasyMock.capture(accountCaptured))).andReturn(account);
}
final Capture<PlatformMessage> msgCaptured = Capture.newInstance(CaptureType.ALL);
int expectedMessageSent = notificationSent ? 3 : 2;
if (accountSaved) {
EasyMock.expect(bus.send(EasyMock.capture(msgCaptured))).andAnswer(() -> {
// replacedertNotificationSent(msgCaptured.getValue());
return Futures.immediateFuture(null);
}).times(expectedMessageSent);
}
replay();
handler.handleRequest(account, createAccountActivateMessage(account));
if (accountSaved) {
Account accountSaved = accountCaptured.getValue();
replacedertEquals(Account.AccountState.COMPLETE, accountSaved.getState());
}
int index = 0;
if (notificationSent) {
PlatformMessage msgSent = msgCaptured.getValues().get(0);
index++;
replacedertEquals(NotifyRequest.NAME, msgSent.getMessageType());
}
verify();
if (accountSaved) {
PlatformMessage valueChangeMsg1 = msgCaptured.getValues().get(index++);
replacedertEquals(Capability.EVENT_VALUE_CHANGE, valueChangeMsg1.getMessageType());
replacedertEquals(place1.getId().toString(), valueChangeMsg1.getPlaceId());
PlatformMessage valueChangeMsg2 = msgCaptured.getValues().get(index++);
replacedertEquals(Capability.EVENT_VALUE_CHANGE, valueChangeMsg2.getMessageType());
replacedertEquals(place2.getId().toString(), valueChangeMsg2.getPlaceId());
}
}
private void replacedertNotificationSent(PlatformMessage value) {
replacedertEquals(NotifyRequest.NAME, value.getMessageType());
}
private Account createAccount(String state) {
Account account = Fixtures.createAccount();
account.setId(UUID.randomUUID());
account.setOwner(UUID.randomUUID());
account.setState(state);
return account;
}
private Person createPerson() {
Person person = Fixtures.createPerson();
person.setId(UUID.randomUUID());
return person;
}
private Place createPlace(UUID accountId) {
Place place = Fixtures.createPlace();
place.setId(UUID.randomUUID());
place.setAccount(accountId);
return place;
}
private PlatformMessage createAccountActivateMessage(Account account) {
MessageBody msgBody = ActivateRequest.instance();
return PlatformMessage.buildMessage(msgBody, clientAddress, Address.fromString(account.getAddress())).isRequestMessage(true).withCorrelationId("correlationid").create();
}
}
16
Source : PromoteToAccountHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced PromoteToAccountHandler implements ContextualRequestMessageHandler<Person> {
private final PersonDAO personDao;
private final AccountDAO accountDao;
private final PlaceDAO placeDao;
private final AuthorizationGrantDAO authGrantDao;
private final BeanAttributesTransformer<Account> accountTransform;
private final BeanAttributesTransformer<Place> placeTransform;
private final PlatformMessageBus bus;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject(optional = true)
@Named("default.service.level")
private String defaultServiceLevel = "basic";
@Inject
public PromoteToAccountHandler(PersonDAO personDao, AccountDAO accountDao, PlaceDAO placeDao, AuthorizationGrantDAO authGrantDao, BeanAttributesTransformer<Account> accountTransform, BeanAttributesTransformer<Place> placeTransform, PlatformMessageBus bus, PlacePopulationCacheManager populationCacheMgr) {
this.personDao = personDao;
this.accountDao = accountDao;
this.placeDao = placeDao;
this.authGrantDao = authGrantDao;
this.accountTransform = accountTransform;
this.placeTransform = placeTransform;
this.bus = bus;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public String getMessageType() {
return PersonCapability.PromoteToAccountRequest.NAME;
}
@Override
public MessageBody handleRequest(Person context, PlatformMessage msg) {
MessageBody body = msg.getValue();
List<AuthorizationGrant> grants = new LinkedList<>(authGrantDao.findForEnreplacedy(context.getId()));
validate(body, context, grants, msg.getActor());
UUID placeId = UUID.randomUUID();
UUID accountId = UUID.randomUUID();
boolean succeeded = false;
Account account = null;
Place place = null;
try {
account = new Account();
account.setId(accountId);
account.setState("ABOUT_YOUR_HOME");
account.setBillable(true);
Set<UUID> placeIDs = new HashSet<>();
placeIDs.add(placeId);
account.setPlaceIDs(placeIDs);
account.setOwner(context.getId());
account = accountDao.create(account);
place = placeTransform.transform(PersonCapability.PromoteToAccountRequest.getPlace(body));
place.setId(placeId);
place.setServiceLevel(ServiceLevel.fromString(defaultServiceLevel));
place.setAccount(account.getId());
place.setPrimary(true);
place = placeDao.create(place);
AuthorizationGrant defaultGrant = new AuthorizationGrant();
defaultGrant.setAccountId(account.getId());
defaultGrant.setAccountOwner(true);
defaultGrant.setEnreplacedyId(context.getId());
defaultGrant.setPlaceId(place.getId());
defaultGrant.setPlaceName(place.getName());
defaultGrant.addPermissions("*:*:*");
authGrantDao.save(defaultGrant);
grants.add(defaultGrant);
context.setCurrPlace(placeId);
personDao.update(context);
sendCurrPlaceValueChange(context, grants);
emitEvent(account, place);
succeeded = true;
} finally {
if (!succeeded) {
if (place != null && place.isPersisted()) {
placeDao.delete(place);
}
if (account != null && account.isPersisted()) {
accountDao.delete(account);
}
context.setCurrPlace(null);
personDao.update(context);
throw new ErrorEventException(Errors.CODE_GENERIC, "unable to create account");
}
}
return PersonCapability.PromoteToAccountResponse.builder().withAccount(accountTransform.transform(account)).withPlace(placeTransform.transform(place)).build();
}
private void emitEvent(Account account, Place place) {
// emit added event for the account
MessageBody body = MessageBody.buildMessage(Capability.EVENT_ADDED, accountTransform.transform(account));
PlatformMessage event = PlatformMessage.buildBroadcast(body, Address.fromString(account.getAddress())).withPlaceId(place.getId()).withPopulation(place.getPopulation()).create();
bus.send(event);
// emit added event for the place
MessageBody eventBodyForPlace = MessageBody.buildMessage(Capability.EVENT_ADDED, placeTransform.transform(place));
PlatformMessage eventForPlace = PlatformMessage.buildBroadcast(eventBodyForPlace, Address.fromString(place.getAddress())).withPlaceId(place.getId()).withPopulation(place.getPopulation()).create();
bus.send(eventForPlace);
}
private void sendCurrPlaceValueChange(Person person, List<AuthorizationGrant> grants) {
MessageBody body = MessageBody.buildMessage(Capability.EVENT_VALUE_CHANGE, ImmutableMap.of(PersonCapability.ATTR_CURRPLACE, person.getCurrPlace().toString()));
Address addr = Address.fromString(person.getAddress());
grants.forEach((g) -> {
PlatformMessage msg = PlatformMessage.buildBroadcast(body, addr).withPlaceId(g.getPlaceId()).withPopulation(populationCacheMgr.getPopulationByPlaceId(g.getPlaceId())).create();
bus.send(msg);
});
}
private void validate(MessageBody body, Person context, List<AuthorizationGrant> grants, Address actor) {
Errors.replacedertRequiredParam(PersonCapability.PromoteToAccountRequest.getPlace(body), "place");
if (!context.getHasLogin()) {
throw new ErrorEventException(Errors.invalidRequest("person does not have a login"));
}
if (grants.stream().anyMatch((g) -> {
return g.isAccountOwner();
})) {
throw new ErrorEventException(Errors.invalidRequest("person is already an account owner"));
}
if (!actor.getRepresentation().contains("icst") && !Objects.equal(context.getAddress(), actor.getRepresentation())) {
throw new ErrorEventException(Errors.invalidRequest("a person may only be promoted to an account by themselves or icst"));
}
}
}
16
Source : HubRegistry.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced HubRegistry implements ParreplacedionListener {
private static final Logger logger = LoggerFactory.getLogger(HubRegistry.clreplaced);
private final HubRegistryMetrics metrics;
private final Clock clock;
private final HubDAO hubDao;
private final Parreplacedioner parreplacedioner;
private final PlatformMessageBus platformBus;
private final ScheduledExecutorService executor;
private final ConcurrentMap<String, HubState> hubs;
private final long offlineTimeoutMs;
private final long timeoutIntervalMs;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public HubRegistry(Clock clock, HubDAO hubDao, Parreplacedioner parreplacedioner, PlatformMessageBus platformBus, HubRegistryConfig config, PlacePopulationCacheManager populationCacheMgr) {
this.metrics = new HubRegistryMetrics(IrisMetrics.metrics("service.platform.hubregistry"));
this.clock = clock;
this.hubDao = hubDao;
this.parreplacedioner = parreplacedioner;
this.platformBus = platformBus;
this.populationCacheMgr = populationCacheMgr;
this.offlineTimeoutMs = TimeUnit.MINUTES.toMillis(config.getOfflineTimeoutMin());
this.timeoutIntervalMs = TimeUnit.SECONDS.toMillis(config.getTimeoutIntervalSec());
this.executor = ThreadPoolBuilder.newSingleThreadedScheduler("hub-heartbeat-watchdog");
this.hubs = new ConcurrentHashMap<>();
}
@WarmUp
public void start() {
parreplacedioner.addParreplacedionListener(this);
executor.scheduleWithFixedDelay(() -> timeout(), timeoutIntervalMs, timeoutIntervalMs, TimeUnit.MILLISECONDS);
}
@PreDestroy
public void stop() {
executor.shutdownNow();
}
public int getOnlineHubs() {
return hubs.size();
}
// note this will only be valid for hub ids replacedociated with the given parreplacedion
public boolean isOnline(String hubId) {
return hubs.get(hubId) != null;
}
/**
* Called when a hub comes online, either via connected message or
* a heartbeat.
* @param hubId
* The id of the hub that came online.
* @param parreplacedionId
* The parreplacedion replacedociated with the hub. When the hub is replacedociated
* with a place this will be based on the place id. When the hub
* is not replacedociated with a place it will be based on the hub id.
* @param hubBridge
* The bridge the hub is replacedociated with. This is to prevent invalid
* disconnect events when switching hub bridges.
*/
public void online(String hubId, int parreplacedionId, String hubBridge) {
try {
hubs.computeIfAbsent(hubId, (ha) -> this.connected(hubId, parreplacedionId)).updateHeartbeat(hubBridge, clock.millis());
} catch (Exception e) {
logger.warn("Unable to mark hub [{}] as online", hubId, e);
}
}
public void offline(String hubId, String hubBridge) {
HubState state = hubs.get(hubId);
if (state == null) {
logger.debug("Received disconnected for untracked hub [{}]", hubId);
disconnected(hubId);
} else if (state.offline(hubBridge, clock.millis() - offlineTimeoutMs) && hubs.remove(hubId, state)) {
logger.debug("Hub disconnected [{}]", hubId);
metrics.onDisconnected();
disconnected(hubId);
} else {
logger.debug("Hub reconnected [{}]", hubId);
}
}
/**
* Removes the hub from being tracked here, this generally happens due to a change in
* parreplacedion membership.
* @param hubId
*/
public boolean remove(String hubId) {
return hubs.remove(hubId) != null;
}
@Override
public void onParreplacedionsChanged(ParreplacedionChangedEvent event) {
removeHubsFromOldParreplacedions(event.getRemovedParreplacedions());
addHubsFromNewParreplacedions(event.getAddedParreplacedions());
}
protected void timeout() {
logger.info("Checking for expired hubs");
long expirationTime = clock.millis() - offlineTimeoutMs;
for (HubState state : hubs.values()) {
if (state.lastHeartbeat < expirationTime) {
if (hubs.remove(state.getHubId(), state)) {
try {
onTimeout(state.getHubId());
} catch (Exception e) {
logger.warn("Error sending timeout for [{}]", state.getHubId(), e);
}
}
}
}
}
protected void onTimeout(String hubId) {
logger.debug("Timing out hub [{}]", hubId);
metrics.onTimeout();
Hub hub = hubDao.findById(hubId);
if (hub == null) {
logger.warn("Untracked hub timed out: [{}]", hubId);
return;
}
sendDisconnected(hubId, hub.getPlace());
disconnected(hubId, hub.getPlace());
}
protected void sendDisconnected(String hubId, UUID placeId) {
Address address = Address.hubService(hubId, HubCapability.NAMESPACE);
MessageBody disconnected = HubCapability.HubDisconnectedEvent.instance();
broadcast(address, placeId, disconnected);
}
private HubState connected(String hubId, int parreplacedionId) {
// note a db outage will prevent the hub from being marked online
// but it should keep retrying as more heartbeats are received
Map<String, Object> event = hubDao.connected(hubId);
if (MapUtils.isNotEmpty(event)) {
logger.debug("Marking hub [{}] online due to heartbeat", hubId);
// need to load the hub to get the placeid
Hub hub = hubDao.findById(hubId);
if (hub != null) {
Address address = Address.hubService(hubId, HubCapability.NAMESPACE);
MessageBody vc = MessageBody.buildMessage(Capability.EVENT_VALUE_CHANGE, event);
broadcast(address, hub.getPlace(), vc);
}
}
return new HubState(hubId, parreplacedionId);
}
private void disconnected(String hubId) {
Hub hub = hubDao.findById(hubId);
if (hub == null) {
logger.warn("Untracked hub disconnected: [{}]", hubId);
return;
}
UUID placeId = hub.getPlace();
disconnected(hubId, placeId);
}
private void disconnected(String hubId, UUID placeId) {
Map<String, Object> event = hubDao.disconnected(hubId);
if (MapUtils.isNotEmpty(event)) {
Address address = Address.hubService(hubId, HubCapability.NAMESPACE);
MessageBody vc = MessageBody.buildMessage(Capability.EVENT_VALUE_CHANGE, event);
broadcast(address, placeId, vc);
}
}
private void putIfOnline(Hub hub, int parreplacedionId, long ts) {
if (HubCapability.STATE_DOWN.equals(hub.getState())) {
// skip this
} else {
hubs.putIfAbsent(hub.getId(), new HubState(hub.getId(), parreplacedionId, ts));
}
}
private void broadcast(Address address, UUID placeId, MessageBody payload) {
PlatformMessage message = PlatformMessage.buildBroadcast(payload, address).withPlaceId(placeId).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeId)).create();
platformBus.send(message);
}
private void addHubsFromNewParreplacedions(Set<Integer> addedParreplacedions) {
if (addedParreplacedions == null) {
return;
}
ForkJoinPool pool = ForkJoinPool.commonPool();
List<ForkJoinTask<?>> results = new ArrayList<>(addedParreplacedions.size());
long ts = clock.millis();
logger.info("Initializing hub registry");
for (Integer parreplacedionId : addedParreplacedions) {
ForkJoinTask<?> result = pool.submit(() -> {
logger.info("Loading hubs for parreplacedion [{}]...", parreplacedionId);
hubDao.streamByParreplacedionId(parreplacedionId).forEach((hub) -> putIfOnline(hub, parreplacedionId, ts));
});
results.add(result);
}
for (ForkJoinTask<?> result : results) {
try {
result.join();
} catch (Exception e) {
logger.warn("Error loading hubs", e);
}
}
logger.info("Hub registry loaded");
}
private void removeHubsFromOldParreplacedions(Set<Integer> removedParreplacedions) {
if (removedParreplacedions.isEmpty()) {
return;
}
Iterator<HubState> it = hubs.values().iterator();
while (it.hasNext()) {
HubState state = it.next();
int parreplacedionId = state.getParreplacedionId();
if (removedParreplacedions.contains(parreplacedionId)) {
it.remove();
}
}
}
private static clreplaced HubState {
private final String hubId;
private final int parreplacedionId;
private final Map<String, Long> heartbeats;
private volatile long lastHeartbeat;
HubState(String hubId, int parreplacedionId) {
this.hubId = hubId;
this.parreplacedionId = parreplacedionId;
this.heartbeats = new HashMap<>(4);
}
HubState(String hubId, int parreplacedionId, long timestamp) {
this.hubId = hubId;
this.parreplacedionId = parreplacedionId;
this.lastHeartbeat = timestamp;
this.heartbeats = new HashMap<>(4);
}
String getHubId() {
return hubId;
}
int getParreplacedionId() {
return parreplacedionId;
}
void updateHeartbeat(String hubbridge, long ts) {
this.lastHeartbeat = ts;
synchronized (heartbeats) {
this.heartbeats.put(hubbridge, ts);
}
}
boolean offline(String hubBridge, long expirationTime) {
synchronized (heartbeats) {
this.lastHeartbeat = 0;
this.heartbeats.remove(hubBridge);
Iterator<Long> timestamps = this.heartbeats.values().iterator();
while (timestamps.hasNext()) {
long ts = timestamps.next();
if (ts < expirationTime) {
timestamps.remove();
} else if (ts > lastHeartbeat) {
lastHeartbeat = ts;
}
}
for (long ts : this.heartbeats.values()) {
if (this.lastHeartbeat < ts) {
this.lastHeartbeat = ts;
}
}
}
return this.lastHeartbeat == 0;
}
}
private clreplaced HubRegistryMetrics {
private final Counter timedout;
private final Counter disconnected;
HubRegistryMetrics(IrisMetricSet metrics) {
disconnected = metrics.counter("disconnected");
timedout = metrics.counter("timedout");
metrics.gauge("online", (Supplier<Integer>) () -> getOnlineHubs());
}
public void onDisconnected() {
disconnected.inc();
}
public void onTimeout() {
timedout.inc();
}
}
}
16
Source : HubDeleteHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced HubDeleteHandler implements ContextualRequestMessageHandler<Hub> {
private static final Logger logger = LoggerFactory.getLogger(HubDeleteHandler.clreplaced);
private final HubDAO hubDao;
private final PlatformMessageBus bus;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public HubDeleteHandler(HubDAO hubDao, PlatformMessageBus bus, PlacePopulationCacheManager populationCacheMgr) {
this.hubDao = hubDao;
this.bus = bus;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public String getMessageType() {
return HubCapability.DeleteRequest.NAME;
}
@Override
public MessageBody handleRequest(Hub context, PlatformMessage msg) {
deleteHub(context);
return HubCapability.DeleteResponse.instance();
}
protected void deleteHub(Hub hub) {
UUID placeId = hub.getPlace();
String population = populationCacheMgr.getPopulationByPlaceId(hub.getPlace());
PlatformMessage deregister = PlatformMessage.buildMessage(HubAdvancedCapability.DeregisterEvent.instance(), Address.platformService(PlatformConstants.SERVICE_HUB), Address.fromString(hub.getAddress())).withPlaceId(placeId).withPopulation(population).create();
bus.send(deregister);
hubDao.delete(hub);
PlatformMessage deleted = PlatformMessage.buildBroadcast(MessageBody.buildMessage(Capability.EVENT_DELETED, ImmutableMap.of()), Address.fromString(hub.getAddress())).withPlaceId(placeId).withPopulation(population).create();
bus.send(deleted);
}
}
16
Source : AccountDeleteHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Singleton
public clreplaced AccountDeleteHandler implements ContextualRequestMessageHandler<Account> {
private static final Logger logger = LoggerFactory.getLogger(AccountDeleteHandler.clreplaced);
private static final int RECURLY_TIMEOUT_SEC = 5;
private final AccountDAO accountDao;
private final PersonDAO personDao;
private final PersonPlacereplacedocDAO personPlacereplacedocDao;
private final AuthorizationGrantDAO authGrantDao;
private final PreferencesDAO preferencesDao;
private final BillingClient billingClient;
private final PlatformMessageBus bus;
private final PlaceDeleter placeDeleter;
private final PlacePopulationCacheManager populationCacheMgr;
@Inject
public AccountDeleteHandler(AccountDAO accountDao, PersonDAO personDao, PersonPlacereplacedocDAO personPlacereplacedocDao, AuthorizationGrantDAO authGrantDao, PreferencesDAO preferencesDao, BillingClient billingClient, PlaceDeleter placeDeleter, PlatformMessageBus bus, PlacePopulationCacheManager populationCacheMgr) {
this.accountDao = accountDao;
this.personDao = personDao;
this.personPlacereplacedocDao = personPlacereplacedocDao;
this.authGrantDao = authGrantDao;
this.preferencesDao = preferencesDao;
this.billingClient = billingClient;
this.placeDeleter = placeDeleter;
this.bus = bus;
this.populationCacheMgr = populationCacheMgr;
}
@Override
public String getMessageType() {
return AccountCapability.DeleteRequest.NAME;
}
@Override
public MessageBody handleRequest(Account context, PlatformMessage msg) {
Boolean deleteLogin = AccountCapability.DeleteRequest.getDeleteOwnerLogin(msg.getValue());
deleteLogin = deleteLogin == null ? false : deleteLogin;
try {
if (billingAccountExists(context)) {
if (!closeBilling(context)) {
return ErrorEvent.fromCode("account.close.failed", "Error closing the billing account.");
}
doDeleteAccount(context, msg.getPlaceId(), deleteLogin);
} else {
doDeleteAccount(context, msg.getPlaceId(), deleteLogin);
}
return AccountCapability.DeleteResponse.instance();
} catch (IllegalArgumentException iae) {
logger.error("Invalid argument ", iae);
return Errors.fromCode("invalid.argument", iae.getMessage());
} catch (Throwable t) {
if (t.getCause() instanceof TransactionErrorException) {
logger.debug("Transaction Error {}", t);
TransactionErrorException e = (TransactionErrorException) t.getCause();
return Errors.fromCode(e.getErrorCode(), e.getCustomerMessage());
} else {
logger.error("Failed to close billing account", t);
return ErrorEvent.fromCode("account.close.failed", "Error closing the billing account.");
}
}
}
private boolean closeBilling(Account account) throws Exception {
return billingClient.closeAccount(account.getId().toString()).get(RECURLY_TIMEOUT_SEC, TimeUnit.SECONDS);
}
private void doDeleteAccount(Account account, String placeId, boolean deleteLogin) {
accountDao.delete(account);
Person owner = personDao.findById(account.getOwner());
sendNotifications(account, owner, placeId);
account.getPlaceIDs().forEach((p) -> deletePlace(account.getAddress(), p));
if (deleteLogin) {
deleteAccountOwner(account, owner, placeId);
} else {
owner.setCurrPlace(null);
owner.setAccountId(null);
personDao.update(owner);
emitOwnerValueChange(owner);
}
}
private void emitOwnerValueChange(Person owner) {
MessageBody body = MessageBody.buildMessage(Capability.EVENT_VALUE_CHANGE, ImmutableMap.of(PersonCapability.ATTR_CURRPLACE, "", PersonCapability.ATTR_HASPIN, false, PersonCapability.ATTR_PLACESWITHPIN, owner.getPlacesWithPin()));
authGrantDao.findForEnreplacedy(owner.getId()).forEach((g) -> {
PlatformMessage evt = PlatformMessage.buildBroadcast(body, Address.fromString(owner.getAddress())).withPlaceId(g.getPlaceId()).withPopulation(populationCacheMgr.getPopulationByPlaceId(g.getPlaceId())).create();
bus.send(evt);
});
}
private void sendNotifications(Account account, Person owner, String placeId) {
EmailRecipient recipient = new EmailRecipient();
recipient.setEmail(owner.getEmail());
recipient.setFirstName(owner.getFirstName());
recipient.setLastName(owner.getLastName());
Notifications.sendEmailNotification(bus, recipient, placeId, populationCacheMgr.getPopulationByPlaceId(placeId), Notifications.AccountRemoved.KEY, ImmutableMap.<String, String>of(Notifications.AccountRemoved.PARAM_PERSON_FIRSTNAME, owner.getFirstName() == null ? "" : owner.getFirstName(), Notifications.AccountRemoved.PARAM_PERSON_LASTNAME, owner.getLastName() == null ? "" : owner.getLastName()), Address.platformService(PlatformConstants.SERVICE_ACCOUNTS));
}
private void emitAccountDeletedEvent(String accountAddress, String placeId) {
MessageBody body = MessageBody.buildMessage(Capability.EVENT_DELETED, ImmutableMap.of());
PlatformMessage event = PlatformMessage.buildBroadcast(body, Address.fromString(accountAddress)).withPlaceId(placeId).withPopulation(populationCacheMgr.getPopulationByPlaceId(placeId)).create();
bus.send(event);
}
// emit this after deleting the account record
private void deletePlace(String accountAddress, UUID placeId) {
if (placeId != null) {
Place curPlace = placeDeleter.getPlace(placeId);
if (curPlace != null) {
placeDeleter.deletePlace(curPlace, false);
emitAccountDeletedEvent(accountAddress, placeId.toString());
}
}
}
private void deleteAccountOwner(Account account, Person owner, String placeId) {
List<String> places = personPlacereplacedocDao.listPlaceAccessForPerson(owner.getId()).stream().map(pad -> pad.getPlaceId()).collect(Collectors.toList());
// Place is deleted prior to invocation of this method; primary place may be missing from this list.
if (!places.contains(placeId)) {
places.add(placeId);
}
preferencesDao.deleteForPerson(owner.getId());
authGrantDao.removeGrantsForEnreplacedy(owner.getId());
personDao.delete(owner);
for (String thisPlace : places) {
MessageBody body = MessageBody.buildMessage(Capability.EVENT_DELETED, ImmutableMap.of("bootSession", true));
PlatformMessage evt = PlatformMessage.buildBroadcast(body, Address.fromString(owner.getAddress())).withPlaceId(thisPlace).withPopulation(populationCacheMgr.getPopulationByPlaceId(thisPlace)).create();
bus.send(evt);
}
}
private boolean billingAccountExists(Account account) throws Throwable {
try {
billingClient.getAccount(account.getId().toString()).get(RECURLY_TIMEOUT_SEC, TimeUnit.SECONDS);
return true;
} catch (ExecutionException ee) {
Throwable cause = ee.getCause();
if (apiErrorWasNotFound(cause)) {
return false;
}
throw cause;
} catch (Exception e) {
throw e;
}
}
private boolean apiErrorWasNotFound(Throwable cause) {
if (cause instanceof BillingEnreplacedyNotFoundException) {
return true;
}
// TODO: WE CAN PROBABLY REMOVE BELOW, BECAUSE THIS LOGIC WAS PUSHED IN TO THE RECURLY CLIENT AS IT CONTAINS RECURLY SPECIFIC CODE
if (cause instanceof RecurlyAPIErrorException) {
RecurlyAPIErrorException recurlyException = (RecurlyAPIErrorException) cause;
RecurlyErrors errors = recurlyException.getErrors();
for (int i = 0; i < errors.size(); i++) {
RecurlyError error = errors.get(i);
if (error.getErrorSymbol().equals("not_found")) {
return true;
}
}
}
return false;
}
}
16
Source : TestTwilioAckScriptHandler.java
with Apache License 2.0
from arcus-smart-home
with Apache License 2.0
from arcus-smart-home
@Mocks({ PlatformMessageBus.clreplaced, BridgeMetrics.clreplaced, FullHttpRequest.clreplaced, ChannelHandlerContext.clreplaced, HttpHeaders.clreplaced, PersonDAO.clreplaced, PlaceDAO.clreplaced, AccountDAO.clreplaced, TemplateService.clreplaced, NotificationAuditor.clreplaced, PlacePopulationCacheManager.clreplaced })
@Modules({ UspsDataServiceModule.clreplaced })
public clreplaced TestTwilioAckScriptHandler extends IrisMockTestCase {
@Inject
private TwilioAckScriptHandler handler;
@Inject
private FullHttpRequest request;
@Inject
private ChannelHandlerContext ctx;
@Inject
private HttpHeaders httpHeaders;
@Inject
private PersonDAO personDAO;
@Inject
private PlaceDAO placeDAO;
@Inject
private NotificationAuditor auditor;
@Inject
private Person person;
@Inject
private Place place;
@Inject
private PlatformMessageBus bus;
@Inject
private PlacePopulationCacheManager populationCacheMgr;
private UUID personID = UUID.randomUUID();
private UUID placeId = UUID.randomUUID();
private String sig;
private URIBuilder builder;
private long timestamp = new Date().getTime();
@Override
protected Set<String> configs() {
Set<String> configs = super.configs();
configs.add("src/test/resources/TestTwilioAckScriptHandler.properties");
return configs;
}
@Before
public void setUp() throws Exception {
super.setUp();
builder = buildParameters(null);
FieldUtils.writeField(handler, "twilioAccountAuth", "AUTHKEY", true);
sig = Base64.encodeToString(HmacUtils.hmacSha1("AUTHKEY", TwilioHelper.PROTOCOL_HTTPS + "somehost" + builder.toString()));
EasyMock.expect(request.getUri()).andReturn(builder.toString()).anyTimes();
EasyMock.expect(request.getMethod()).andReturn(HttpMethod.GET);
EasyMock.expect(request.headers()).andReturn(httpHeaders).anyTimes();
EasyMock.expect(httpHeaders.contains(TwilioHelper.SIGNATURE_HEADER_KEY)).andReturn(true).anyTimes();
EasyMock.expect(httpHeaders.get(TwilioHelper.SIGNATURE_HEADER_KEY)).andReturn(sig).anyTimes();
EasyMock.expect(httpHeaders.get(TwilioHelper.HOST_HEADER_KEY)).andReturn("somehost").anyTimes();
EasyMock.expect(personDAO.findById(personID)).andReturn(person);
EasyMock.expect(placeDAO.findById(placeId)).andReturn(place);
EasyMock.expect(populationCacheMgr.getPopulationByPlaceId(EasyMock.anyObject(UUID.clreplaced))).andReturn(Population.NAME_GENERAL).anyTimes();
}
@Test
public void handleVerifyFailed() throws Exception {
replay();
FieldUtils.writeField(handler, "twilioAccountAuth", "AUTHKEY2", true);
TemplatedResponse response = handler.doHandle(request, ctx);
replacedertEquals(HttpResponseStatus.NOT_FOUND, response.getResponseStatus().get());
}
@SuppressWarnings("unchecked")
@Test
public void handleAcknowledged() throws Exception {
auditor.log("place:" + placeId, Instant.ofEpochMilli(timestamp), AuditEventState.DELIVERED, TwilioAckScriptHandler.ACKNOWLEDGED_MESSAGE);
EasyMock.expectLastCall();
EasyMock.expect(bus.send(EasyMock.anyObject(PlatformMessage.clreplaced))).andReturn(null);
replay();
TemplatedResponse response = handler.doHandle(request, ctx);
Map<String, Object> context = (Map<String, Object>) response.getContext();
replacedertEquals("test", response.getTemplateId().get());
replacedertEquals(person, context.get("_person"));
System.out.println("Callback URL: " + context.get("callbackURL"));
replacedertEquals("/ivr/script/ack?script=test¬ificationId=place%3A" + placeId.toString() + "¬ificationTimestamp=" + timestamp + "&placeId=" + placeId.toString() + "&personId=" + personID.toString() + "&retryCount=0", context.get("callbackURL"));
replacedertEquals("acknowledged", response.getSectionId().get());
verify();
}
@Test
public void handleRetryTimeout() throws Exception {
EasyMock.reset(request);
EasyMock.expect(bus.send(EasyMock.anyObject(PlatformMessage.clreplaced))).andReturn(null);
EasyMock.expect(request.headers()).andReturn(httpHeaders).anyTimes();
EasyMock.expect(request.getMethod()).andReturn(HttpMethod.GET).anyTimes();
EasyMock.expect(request.getUri()).andReturn(buildParameters(ImmutableMap.of(TwilioAckScriptHandler.RETRY_COUNT_PARAM, "3")).toString()).anyTimes();
FieldUtils.writeField(handler, "twilioVerifyAuth", false, true);
auditor.log("place:" + placeId, Instant.ofEpochMilli(timestamp), AuditEventState.FAILED, TwilioScriptHandler.TIMEOUT_MESSAGE);
EasyMock.expectLastCall();
replay();
handler.doHandle(request, ctx);
verify();
}
private URIBuilder buildParameters(Map<String, String> params) throws Exception {
URIBuilder builder = new URIBuilder("/ivr/script");
if (params != null) {
for (Map.Entry<String, String> entry : params.entrySet()) {
builder.addParameter(entry.getKey(), entry.getValue());
}
}
builder.addParameter(TwilioScriptHandler.SCRIPT_PARAM, "test").addParameter(TwilioScriptHandler.STEP_PARAM, "submitAck").addParameter(TwilioScriptHandler.TWILIO_DIGITS_PARAM, "#").addParameter(TwilioHelper.PERSON_ID_PARAM_NAME, personID.toString()).addParameter(TwilioHelper.PLACE_ID_PARAM_NAME, placeId.toString()).addParameter(TwilioHelper.NOTIFICATION_ID_PARAM_NAME, "place:" + placeId).addParameter(TwilioScriptHandler.CUSTOM_MESSAGE_PARAM, "test").addParameter(TwilioHelper.NOTIFICATION_EVENT_TIME_PARAM_NAME, Long.toString(timestamp));
return builder;
}
}
See More Examples