class AutoUpdateManager {

    public void receiveCommand(ItemCommandEvent commandEvent, Item item) {
        if (!enabled) {
            return;
        }
        final String itemName = commandEvent.getItemName();
        final Command command = commandEvent.getItemCommand();
        if (command instanceof State) {
            final State state = (State) command;

            Recommendation autoUpdate = shouldAutoUpdate(itemName);

            // consider user-override via item meta-data
            MetadataKey key = new MetadataKey(AUTOUPDATE_KEY, itemName);
            Metadata metadata = metadataRegistry.get(key);
            if (metadata != null && !metadata.getValue().trim().isEmpty()) {
                boolean override = Boolean.parseBoolean(metadata.getValue());
                if (override) {
                    logger.trace("Auto update strategy {} overriden by item metadata to REQUIRED", autoUpdate);
                    autoUpdate = Recommendation.REQUIRED;
                } else {
                    logger.trace("Auto update strategy {} overriden by item metadata to DONT", autoUpdate);
                    autoUpdate = Recommendation.DONT;
                }
            }

            switch (autoUpdate) {
                case REQUIRED:
                    logger.trace("Automatically updating item '{}' because no channel is linked", itemName);
                    postUpdate(item, state, EVENT_SOURCE);
                    break;
                case RECOMMENDED:
                    logger.trace("Automatically updating item '{}' because no channel does it", itemName);
                    postUpdate(item, state, EVENT_SOURCE);
                    break;
                case OPTIMISTIC:
                    logger.trace("Optimistically updating item '{}'", itemName);
                    postPrediction(item, state, false);
                    if (sendOptimisticUpdates) {
                        postUpdate(item, state, EVENT_SOURCE_OPTIMISTIC);
                    }
                    break;
                case DONT:
                    logger.trace("Won't update item '{}' as it was vetoed.", itemName);
                    break;
                case REVERT:
                    logger.trace("Sending current item state to revert controls '{}'", itemName);
                    postPrediction(item, item.getState(), true);
                    break;
            }
        }
    }

    @Activate public  AutoUpdateManager(Map<String, @Nullable Object> configuration,
            final @Reference ChannelTypeRegistry channelTypeRegistry, //
            final @Reference EventPublisher eventPublisher,
            final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry,
            final @Reference MetadataRegistry metadataRegistry, //
            final @Reference ThingRegistry thingRegistry);

}