class ModifyFeaturePropertiesStrategy extends AbstractThingCommandStrategy<ModifyFeatureProperties> {

    @Override
    protected Result<ThingEvent> doApply(final Context<ThingId> context,
            @Nullable final Thing thing,
            final long nextRevision,
            final ModifyFeatureProperties command,
            @Nullable final Metadata metadata) {

        final String featureId = command.getFeatureId();

        final Thing nonNullThing = getEntityOrThrow(thing);

        final JsonObject thingWithoutProperties = nonNullThing.removeFeatureProperties(featureId).toJson();
        final JsonObject propertiesJsonObject = command.getProperties().toJson();

        ThingCommandSizeValidator.getInstance().ensureValidSize(
                () -> {
                    final long lengthWithOutProperties = thingWithoutProperties.getUpperBoundForStringSize();
                    final long propertiesLength = propertiesJsonObject.getUpperBoundForStringSize()
                            + "properties".length() + featureId.length() + 5L;
                    return lengthWithOutProperties + propertiesLength;
                },
                () -> {
                    final long lengthWithOutProperties = thingWithoutProperties.toString().length();
                    final long propertiesLength = propertiesJsonObject.toString().length()
                            + "properties".length() + featureId.length() + 5L;
                    return lengthWithOutProperties + propertiesLength;
                },
                command::getDittoHeaders);

        return extractFeature(command, nonNullThing)
                .map(feature -> getModifyOrCreateResult(feature, context, nextRevision, command, thing, metadata))
                .orElseGet(() -> ResultFactory.newErrorResult(
                        ExceptionFactory.featureNotFound(context.getState(), featureId,
                                command.getDittoHeaders()), command));
    }

      ModifyFeaturePropertiesStrategy();

}