com.iris.population.PlacePopulationCacheManager

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 7

19 Source : BaseChangePinRESTHandler.java
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

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

/**
 */
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

@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

// 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

@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

@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

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

@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

/**
 */
@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

@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

@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

@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

@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

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

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

/**
 */
@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

@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

@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

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

@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

@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

/**
 */
@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

/**
 */
@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

/**
 * 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

@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

@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

@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

/**
 */
@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

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

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

@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

@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

@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

@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

@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

@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

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

@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

@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

@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

/**
 */
@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

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

/**
 */
@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

@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

@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

@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

@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

@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

@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