Search in sources :

Example 1 with VALUE_TIMESTAMP_FIELD_NAME

use of org.openremote.model.AbstractValueTimestampHolder.VALUE_TIMESTAMP_FIELD_NAME in project openremote by openremote.

the class RulesService method processAssetChange.

protected void processAssetChange(ServerAsset asset, PersistenceEvent persistenceEvent) {
    withLock(getClass().getSimpleName() + "::processAssetChange", () -> {
        // We must load the asset from database (only when required), as the
        // persistence event might not contain a completely loaded asset
        BiFunction<Asset, AssetAttribute, AssetState> buildAssetState = (loadedAsset, attribute) -> new AssetState(loadedAsset, attribute.deepCopy(), Source.INTERNAL);
        switch(persistenceEvent.getCause()) {
            case INSERT:
                // New asset has been created so get attributes that have RULE_STATE meta
                List<AssetAttribute> ruleStateAttributes = asset.getAttributesStream().filter(AssetAttribute::isRuleState).collect(Collectors.toList());
                // Build an update with a fully loaded asset
                ruleStateAttributes.forEach(attribute -> {
                    ServerAsset loadedAsset = assetStorageService.find(asset.getId(), true);
                    // If the asset is now gone it was deleted immediately after being inserted, nothing more to do
                    if (loadedAsset == null)
                        return;
                    AssetState assetState = buildAssetState.apply(loadedAsset, attribute);
                    LOG.fine("Asset was persisted (" + persistenceEvent.getCause() + "), inserting fact: " + assetState);
                    updateAssetState(assetState, true, true);
                });
                break;
            case UPDATE:
                int attributesIndex = Arrays.asList(persistenceEvent.getPropertyNames()).indexOf("attributes");
                if (attributesIndex < 0) {
                    return;
                }
                // Fully load the asset
                final Asset loadedAsset = assetStorageService.find(asset.getId(), true);
                // If the asset is now gone it was deleted immediately after being updated, nothing more to do
                if (loadedAsset == null)
                    return;
                // Attributes have possibly changed so need to compare old and new attributes
                // to determine which facts to retract and which to insert
                List<AssetAttribute> oldRuleStateAttributes = attributesFromJson((ObjectValue) persistenceEvent.getPreviousState()[attributesIndex], asset.getId()).filter(AssetAttribute::isRuleState).collect(Collectors.toList());
                List<AssetAttribute> newRuleStateAttributes = attributesFromJson((ObjectValue) persistenceEvent.getCurrentState()[attributesIndex], asset.getId()).filter(AssetAttribute::isRuleState).collect(Collectors.toList());
                // Retract facts for attributes that are obsolete
                getAddedOrModifiedAttributes(newRuleStateAttributes, oldRuleStateAttributes, key -> key.equals(VALUE_TIMESTAMP_FIELD_NAME)).forEach(obsoleteFactAttribute -> {
                    AssetState update = buildAssetState.apply(loadedAsset, obsoleteFactAttribute);
                    LOG.fine("Asset was persisted (" + persistenceEvent.getCause() + "), retracting: " + update);
                    retractAssetState(update);
                });
                // Insert facts for attributes that are new
                getAddedOrModifiedAttributes(oldRuleStateAttributes, newRuleStateAttributes, key -> key.equals(VALUE_TIMESTAMP_FIELD_NAME)).forEach(newFactAttribute -> {
                    AssetState assetState = buildAssetState.apply(loadedAsset, newFactAttribute);
                    LOG.fine("Asset was persisted (" + persistenceEvent.getCause() + "), updating: " + assetState);
                    updateAssetState(assetState, true, true);
                });
                break;
            case DELETE:
                // Retract any facts that were associated with this asset
                asset.getAttributesStream().filter(AssetAttribute::isRuleState).forEach(attribute -> {
                    // We can't load the asset again (it was deleted), so don't use buildAssetState() and
                    // hope that the path of the event asset has been loaded before deletion, although it is
                    // "unlikely" anybody will access it during retraction...
                    AssetState assetState = new AssetState(asset, attribute, Source.INTERNAL);
                    LOG.fine("Asset was persisted (" + persistenceEvent.getCause() + "), retracting fact: " + assetState);
                    retractAssetState(assetState);
                });
                break;
        }
    });
}
Also used : PersistenceEvent(org.openremote.container.persistence.PersistenceEvent) Tenant(org.openremote.model.security.Tenant) java.util(java.util) BiFunction(java.util.function.BiFunction) AssetAttribute.getAddedOrModifiedAttributes(org.openremote.model.asset.AssetAttribute.getAddedOrModifiedAttributes) NotificationService(org.openremote.manager.notification.NotificationService) ObjectValue(org.openremote.model.value.ObjectValue) MapAccess.getString(org.openremote.container.util.MapAccess.getString) GlobalLock.withLockReturning(org.openremote.container.concurrent.GlobalLock.withLockReturning) Container(org.openremote.container.Container) ContainerService(org.openremote.container.ContainerService) PersistenceEvent.isPersistenceEventForEntityType(org.openremote.container.persistence.PersistenceEvent.isPersistenceEventForEntityType) PersistenceService(org.openremote.container.persistence.PersistenceService) ManagerExecutorService(org.openremote.manager.concurrent.ManagerExecutorService) PERSISTENCE_TOPIC(org.openremote.container.persistence.PersistenceEvent.PERSISTENCE_TOPIC) org.openremote.model.rules(org.openremote.model.rules) ManagerIdentityService(org.openremote.manager.security.ManagerIdentityService) Asset(org.openremote.model.asset.Asset) Pair(org.openremote.model.util.Pair) VALUE_TIMESTAMP_FIELD_NAME(org.openremote.model.AbstractValueTimestampHolder.VALUE_TIMESTAMP_FIELD_NAME) AssetAttribute.attributesFromJson(org.openremote.model.asset.AssetAttribute.attributesFromJson) EntityManager(javax.persistence.EntityManager) Logger(java.util.logging.Logger) MessageBrokerSetupService(org.openremote.container.message.MessageBrokerSetupService) Collectors(java.util.stream.Collectors) AssetMeta(org.openremote.model.asset.AssetMeta) org.openremote.manager.asset(org.openremote.manager.asset) AssetQuery(org.openremote.model.asset.AssetQuery) Stream(java.util.stream.Stream) RouteBuilder(org.apache.camel.builder.RouteBuilder) TimerService(org.openremote.container.timer.TimerService) Source(org.openremote.model.attribute.AttributeEvent.Source) AssetAttribute(org.openremote.model.asset.AssetAttribute) FINEST(java.util.logging.Level.FINEST) GlobalLock.withLock(org.openremote.container.concurrent.GlobalLock.withLock) AssetAttribute(org.openremote.model.asset.AssetAttribute) Asset(org.openremote.model.asset.Asset)

Example 2 with VALUE_TIMESTAMP_FIELD_NAME

use of org.openremote.model.AbstractValueTimestampHolder.VALUE_TIMESTAMP_FIELD_NAME in project openremote by openremote.

the class AgentService method processAssetChange.

/**
 * Looks for new, modified and obsolete AGENT_LINK attributes and links / unlinks them
 * with the protocol
 */
protected void processAssetChange(Asset asset, PersistenceEvent persistenceEvent) {
    LOG.finest("Processing asset persistence event: " + persistenceEvent.getCause());
    switch(persistenceEvent.getCause()) {
        case INSERT:
            // Asset insert persistence events can be fired before the agent insert persistence event
            // so need to check that all protocol configs exist - any that don't we will exclude here
            // and handle in agent insert
            // If an agent insert just occurred then we will end up trying to link the attribute again
            // so we keep track of linked attributes to avoid this
            // Link any AGENT_LINK attributes to their referenced protocol
            Map<AssetAttribute, List<AssetAttribute>> groupedAgentLinksAttributes = getGroupedAgentLinkAttributes(asset.getAttributesStream(), attribute -> true, attribute -> LOG.warning("Linked protocol configuration not found: " + attribute));
            groupedAgentLinksAttributes.forEach(this::linkAttributes);
            break;
        case UPDATE:
            List<String> propertyNames = Arrays.asList(persistenceEvent.getPropertyNames());
            // Check if attributes of the asset have been modified
            int attributesIndex = propertyNames.indexOf("attributes");
            if (attributesIndex < 0) {
                return;
            }
            // Attributes have possibly changed so need to compare old and new state to determine any changes to
            // AGENT_LINK attributes
            List<AssetAttribute> oldAgentLinkedAttributes = attributesFromJson((ObjectValue) persistenceEvent.getPreviousState()[attributesIndex], asset.getId()).filter(AgentLink::hasAgentLink).collect(Collectors.toList());
            List<AssetAttribute> newAgentLinkedAttributes = attributesFromJson((ObjectValue) persistenceEvent.getCurrentState()[attributesIndex], asset.getId()).filter(AgentLink::hasAgentLink).collect(Collectors.toList());
            // Unlink thing attributes that are in old but not in new
            getGroupedAgentLinkAttributes(getAddedOrModifiedAttributes(newAgentLinkedAttributes, oldAgentLinkedAttributes, key -> key.equals(VALUE_TIMESTAMP_FIELD_NAME)), attribute -> true).forEach(this::unlinkAttributes);
            // Link thing attributes that are in new but not in old
            getGroupedAgentLinkAttributes(getAddedOrModifiedAttributes(oldAgentLinkedAttributes, newAgentLinkedAttributes, key -> key.equals(VALUE_TIMESTAMP_FIELD_NAME)), attribute -> true, attribute -> LOG.warning("Linked protocol configuration not found: " + attribute)).forEach(this::linkAttributes);
            break;
        case DELETE:
            {
                // Unlink any AGENT_LINK attributes from the referenced protocol
                Map<AssetAttribute, List<AssetAttribute>> groupedAgentLinkAndProtocolAttributes = getGroupedAgentLinkAttributes(asset.getAttributesStream(), attribute -> true);
                groupedAgentLinkAndProtocolAttributes.forEach(this::unlinkAttributes);
                break;
            }
    }
}
Also used : PersistenceEvent(org.openremote.container.persistence.PersistenceEvent) java.util(java.util) ClientRole(org.openremote.model.security.ClientRole) WebService(org.openremote.container.web.WebService) AssetAttribute.getAddedOrModifiedAttributes(org.openremote.model.asset.AssetAttribute.getAddedOrModifiedAttributes) ConnectionStatus(org.openremote.model.asset.agent.ConnectionStatus) AttributeRef(org.openremote.model.attribute.AttributeRef) SENSOR_QUEUE(org.openremote.agent.protocol.Protocol.SENSOR_QUEUE) ASSET_QUEUE(org.openremote.manager.asset.AssetProcessingService.ASSET_QUEUE) ObjectValue(org.openremote.model.value.ObjectValue) Point(com.vividsolutions.jts.geom.Point) Level(java.util.logging.Level) ACTUATOR_TOPIC(org.openremote.agent.protocol.Protocol.ACTUATOR_TOPIC) GlobalLock.withLockReturning(org.openremote.container.concurrent.GlobalLock.withLockReturning) Container(org.openremote.container.Container) TenantFilter(org.openremote.model.event.shared.TenantFilter) ContainerService(org.openremote.container.ContainerService) AttributeEvent(org.openremote.model.attribute.AttributeEvent) org.openremote.model.asset(org.openremote.model.asset) AGENT(org.openremote.model.asset.AssetType.AGENT) AgentLink.getAgentLink(org.openremote.model.asset.agent.AgentLink.getAgentLink) MessageBrokerService(org.openremote.container.message.MessageBrokerService) ManagerIdentityService(org.openremote.manager.security.ManagerIdentityService) SENSOR(org.openremote.model.attribute.AttributeEvent.Source.SENSOR) Predicate(java.util.function.Predicate) Pair(org.openremote.model.util.Pair) VALUE_TIMESTAMP_FIELD_NAME(org.openremote.model.AbstractValueTimestampHolder.VALUE_TIMESTAMP_FIELD_NAME) AssetAttribute.attributesFromJson(org.openremote.model.asset.AssetAttribute.attributesFromJson) ProtocolAssetService(org.openremote.agent.protocol.ProtocolAssetService) EntityManager(javax.persistence.EntityManager) Logger(java.util.logging.Logger) MessageBrokerSetupService(org.openremote.container.message.MessageBrokerSetupService) Collectors(java.util.stream.Collectors) HEADER_SOURCE(org.openremote.model.attribute.AttributeEvent.HEADER_SOURCE) TextUtil.isValidURN(org.openremote.model.util.TextUtil.isValidURN) org.openremote.manager.asset(org.openremote.manager.asset) Consumer(java.util.function.Consumer) ClientEventService(org.openremote.manager.event.ClientEventService) Stream(java.util.stream.Stream) org.openremote.model.asset.agent(org.openremote.model.asset.agent) RouteBuilder(org.apache.camel.builder.RouteBuilder) TimerService(org.openremote.container.timer.TimerService) Source(org.openremote.model.attribute.AttributeEvent.Source) TextUtil.isNullOrEmpty(org.openremote.model.util.TextUtil.isNullOrEmpty) GlobalLock(org.openremote.container.concurrent.GlobalLock) Protocol(org.openremote.agent.protocol.Protocol) GlobalLock.withLock(org.openremote.container.concurrent.GlobalLock.withLock) Point(com.vividsolutions.jts.geom.Point)

Aggregations

java.util (java.util)2 Logger (java.util.logging.Logger)2 Collectors (java.util.stream.Collectors)2 Stream (java.util.stream.Stream)2 EntityManager (javax.persistence.EntityManager)2 RouteBuilder (org.apache.camel.builder.RouteBuilder)2 Container (org.openremote.container.Container)2 ContainerService (org.openremote.container.ContainerService)2 GlobalLock.withLock (org.openremote.container.concurrent.GlobalLock.withLock)2 GlobalLock.withLockReturning (org.openremote.container.concurrent.GlobalLock.withLockReturning)2 MessageBrokerSetupService (org.openremote.container.message.MessageBrokerSetupService)2 PersistenceEvent (org.openremote.container.persistence.PersistenceEvent)2 TimerService (org.openremote.container.timer.TimerService)2 org.openremote.manager.asset (org.openremote.manager.asset)2 ManagerIdentityService (org.openremote.manager.security.ManagerIdentityService)2 VALUE_TIMESTAMP_FIELD_NAME (org.openremote.model.AbstractValueTimestampHolder.VALUE_TIMESTAMP_FIELD_NAME)2 AssetAttribute.attributesFromJson (org.openremote.model.asset.AssetAttribute.attributesFromJson)2 AssetAttribute.getAddedOrModifiedAttributes (org.openremote.model.asset.AssetAttribute.getAddedOrModifiedAttributes)2 Source (org.openremote.model.attribute.AttributeEvent.Source)2 Point (com.vividsolutions.jts.geom.Point)1