Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend min/max/step with rangeUnit #4460

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@
<xs:attribute name="min" type="xs:decimal" use="optional"/>
<xs:attribute name="max" type="xs:decimal" use="optional"/>
<xs:attribute name="step" type="xs:decimal" use="optional"/>
<xs:attribute name="rangeUnit" type="xs:string" use="optional"/>
<xs:attribute name="pattern" type="xs:string" use="optional"/>
<xs:attribute name="readOnly" type="xs:boolean" default="false" use="optional"/>
</xs:complexType>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ static StateDescriptionFragmentEntity mapToEntity(StateDescriptionFragment fragm
entity.maximum = fragment.getMaximum();
entity.minimum = fragment.getMinimum();
entity.step = fragment.getStep();
entity.rangeUnit = fragment.getRangeUnit();
entity.options = fragment.getOptions();
entity.pattern = fragment.getPattern();
entity.isReadOnly = fragment.isReadOnly();
Expand Down Expand Up @@ -371,6 +372,9 @@ static StateDescriptionFragment mapFromEntity(StateDescriptionFragmentEntity ent
if (entity.step != null) {
builder.withStep(Objects.requireNonNull(entity.step));
}
if (entity.rangeUnit != null) {
builder.withRangeUnit(Objects.requireNonNull(entity.rangeUnit));
}
if (entity.options != null) {
builder.withOptions(Objects.requireNonNull(entity.options));
}
Expand Down Expand Up @@ -444,6 +448,7 @@ static class StateDescriptionFragmentEntity {
public @Nullable BigDecimal maximum;
public @Nullable BigDecimal minimum;
public @Nullable BigDecimal step;
public @Nullable String rangeUnit;
public @Nullable List<StateOption> options;
public @Nullable String pattern;
public boolean isReadOnly = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ public class StateDescriptionConverter extends GenericUnmarshaller<StateDescript
public StateDescriptionConverter() {
super(StateDescription.class);

this.attributeMapValidator = new ConverterAttributeMapValidator(new String[][] { { "min", "false" },
{ "max", "false" }, { "step", "false" }, { "pattern", "false" }, { "readOnly", "false" } });
this.attributeMapValidator = new ConverterAttributeMapValidator(
new String[][] { { "min", "false" }, { "max", "false" }, { "step", "false" }, { "rangeUnit", "false" },
{ "pattern", "false" }, { "readOnly", "false" } });
}

private @Nullable BigDecimal toBigDecimal(Map<String, String> attributes, String attribute,
Expand Down Expand Up @@ -123,6 +124,11 @@ private StateOption toChannelStateOption(NodeValue nodeValue) throws ConversionE
builder.withStep(step);
}

String rangeUnit = attributes.get("pattern");
if (rangeUnit != null) {
builder.withRangeUnit(rangeUnit);
}

String pattern = attributes.get("pattern");
if (pattern != null) {
builder.withPattern(pattern);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,15 @@ public class ThingEventFactoryTest {
.withMinimum(BigDecimal.ZERO) //
.withMaximum(new BigDecimal(1000)) //
.withStep(new BigDecimal(100)) //
.withRangeUnit("K") //
.withPattern("%.0f K") //
.build());
private static final String CHANNEL_DESCRIPTION_OLD_STATE_DESCRIPTION_PAYLOAD = JSONCONVERTER
.toJson(StateDescriptionFragmentBuilder.create() //
.withMinimum(BigDecimal.ZERO) //
.withMaximum(new BigDecimal(6000)) //
.withStep(new BigDecimal(100)) //
.withRangeUnit("K") //
.withPattern("%.0f K") //
.build());
private static final String CHANNEL_DESCRIPTION_CHANGED_EVENT_PAYLOAD_NEW_AND_OLD_DESCRIPTION = JSONCONVERTER
Expand Down Expand Up @@ -340,12 +342,14 @@ public void testCreateChannelDescriptionChangedEventOldAndNewStateDescription()
.withMinimum(BigDecimal.ZERO) //
.withMaximum(new BigDecimal(1000)) //
.withStep(new BigDecimal(100)) //
.withRangeUnit("K") //
.withPattern("%.0f K") //
.build();
StateDescriptionFragment oldStateDescriptionFragment = StateDescriptionFragmentBuilder.create() //
.withMinimum(BigDecimal.ZERO) //
.withMaximum(new BigDecimal(6000)) //
.withStep(new BigDecimal(100)) //
.withRangeUnit("K") //
.withPattern("%.0f K") //
.build();
ChannelDescriptionChangedEvent event = ThingEventFactory.createChannelDescriptionChangedEvent(CHANNEL_UID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ public MetadataStateDescriptionFragmentProvider(final @Reference MetadataRegistr
builder.withStep(getBigDecimal(step));
}

Object rangeUnit = metadata.getConfiguration().get("rangeUnit");
if (rangeUnit != null) {
builder.withRangeUnit((String) rangeUnit);
}

Object readOnly = metadata.getConfiguration().get("readOnly");
if (readOnly != null) {
builder.withReadOnly(getBoolean(readOnly));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,16 @@ public class StateDescriptionFragmentImpl implements StateDescriptionFragment {

private static class StateDescriptionImpl extends StateDescription {
StateDescriptionImpl(@Nullable BigDecimal minimum, @Nullable BigDecimal maximum, @Nullable BigDecimal step,
@Nullable String pattern, boolean readOnly, @Nullable List<StateOption> options) {
super(minimum, maximum, step, pattern, readOnly, options);
@Nullable String rangeUnit, @Nullable String pattern, boolean readOnly,
@Nullable List<StateOption> options) {
super(minimum, maximum, step, rangeUnit, pattern, readOnly, options);
}
}

private @Nullable BigDecimal minimum;
private @Nullable BigDecimal maximum;
private @Nullable BigDecimal step;
private @Nullable String rangeUnit;
private @Nullable String pattern;
private @Nullable Boolean readOnly;
private @Nullable List<StateOption> options;
Expand All @@ -59,18 +61,20 @@ public StateDescriptionFragmentImpl() {
* @param minimum minimum value of the state
* @param maximum maximum value of the state
* @param step step size
* @param rangeUnit unit that applies to the min, max and step value
* @param pattern pattern to render the state
* @param readOnly if the state can be changed by the system
* @param options predefined list of options
* @deprecated use {@link StateDescriptionFragmentBuilder} instead.
*/
@Deprecated
public StateDescriptionFragmentImpl(@Nullable BigDecimal minimum, @Nullable BigDecimal maximum,
@Nullable BigDecimal step, @Nullable String pattern, @Nullable Boolean readOnly,
@Nullable BigDecimal step, @Nullable String rangeUnit, @Nullable String pattern, @Nullable Boolean readOnly,
@Nullable List<StateOption> options) {
this.minimum = minimum;
this.maximum = maximum;
this.step = step;
this.rangeUnit = rangeUnit;
this.pattern = pattern;
this.readOnly = readOnly;
this.options = options == null || options.isEmpty() ? List.of() : Collections.unmodifiableList(options);
Expand All @@ -88,6 +92,7 @@ public StateDescriptionFragmentImpl(StateDescription legacy) {
this.minimum = legacy.getMinimum();
this.maximum = legacy.getMaximum();
this.step = legacy.getStep();
this.rangeUnit = legacy.getRangeUnit();
this.pattern = legacy.getPattern();
this.readOnly = Boolean.valueOf(legacy.isReadOnly());
if (!legacy.getOptions().isEmpty()) {
Expand All @@ -104,6 +109,7 @@ public StateDescriptionFragmentImpl(StateDescriptionFragmentImpl source) {
this.minimum = source.getMinimum();
this.maximum = source.getMaximum();
this.step = source.getStep();
this.rangeUnit = source.getRangeUnit();
this.pattern = source.getPattern();
this.readOnly = source.isReadOnly();
this.options = source.getOptions();
Expand Down Expand Up @@ -136,6 +142,15 @@ public void setStep(BigDecimal step) {
this.step = step;
}

@Override
public @Nullable String getRangeUnit() {
return rangeUnit;
}

public void setRangeUnit(String rangeUnit) {
this.rangeUnit = rangeUnit;
}

@Override
public @Nullable String getPattern() {
return pattern;
Expand Down Expand Up @@ -165,12 +180,13 @@ public void setOptions(List<StateOption> options) {

@Override
public @Nullable StateDescription toStateDescription() {
if (minimum == null && maximum == null && step == null && readOnly == null && pattern == null
&& options == null) {
if (minimum == null && maximum == null && step == null && rangeUnit == null && readOnly == null
&& pattern == null && options == null) {
return null;
}
final Boolean ro = readOnly;
return new StateDescriptionImpl(minimum, maximum, step, pattern, ro != null && ro.booleanValue(), options);
return new StateDescriptionImpl(minimum, maximum, step, rangeUnit, pattern, ro != null && ro.booleanValue(),
options);
}

/**
Expand All @@ -190,6 +206,9 @@ public StateDescriptionFragment merge(StateDescriptionFragment fragment) {
if (step == null) {
step = fragment.getStep();
}
if (rangeUnit == null) {
rangeUnit = fragment.getRangeUnit();
}
if (pattern == null) {
pattern = fragment.getPattern();
}
Expand All @@ -209,6 +228,7 @@ public int hashCode() {
result = prime * result + (minimum != null ? minimum.hashCode() : 0);
result = prime * result + (maximum != null ? maximum.hashCode() : 0);
result = prime * result + (step != null ? step.hashCode() : 0);
result = prime * result + (rangeUnit != null ? rangeUnit.hashCode() : 0);
result = prime * result + (pattern != null ? pattern.hashCode() : 0);
result = prime * result + (readOnly ? 1231 : 1237);
result = prime * result + (options != null ? options.hashCode() : 0);
Expand All @@ -228,13 +248,15 @@ public boolean equals(@Nullable Object obj) {
}
StateDescriptionFragmentImpl other = (StateDescriptionFragmentImpl) obj;
return Objects.equals(minimum, other.minimum) && Objects.equals(maximum, other.maximum)
&& Objects.equals(step, other.step) && Objects.equals(pattern, other.pattern)
&& Objects.equals(readOnly, other.readOnly) && Objects.equals(options, other.options);
&& Objects.equals(step, other.step) && Objects.equals(rangeUnit, other.rangeUnit)
&& Objects.equals(pattern, other.pattern) && Objects.equals(readOnly, other.readOnly)
&& Objects.equals(options, other.options);
}

@Override
public String toString() {
return "StateDescription [minimum=" + minimum + ", maximum=" + maximum + ", step=" + step + ", pattern="
+ pattern + ", readOnly=" + readOnly + ", channelStateOptions=" + options + "]";
return "StateDescription [minimum=" + minimum + ", maximum=" + maximum + ", step=" + step + ", rangeUnit="
+ rangeUnit + ", pattern=" + pattern + ", readOnly=" + readOnly + ", channelStateOptions=" + options
+ "]";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class StateDescription {
protected @Nullable final BigDecimal minimum;
protected @Nullable final BigDecimal maximum;
protected @Nullable final BigDecimal step;
protected @Nullable final String rangeUnit;
protected @Nullable final String pattern;
protected final boolean readOnly;
protected final List<StateOption> options;
Expand All @@ -41,15 +42,18 @@ public class StateDescription {
* @param minimum minimum value of the state
* @param maximum maximum value of the state
* @param step step size
* @param rangeUnit unit that applies to the min, max and step value
* @param pattern pattern to render the state
* @param readOnly if the state can be changed by the system
* @param options predefined list of options
*/
protected StateDescription(@Nullable BigDecimal minimum, @Nullable BigDecimal maximum, @Nullable BigDecimal step,
@Nullable String pattern, boolean readOnly, @Nullable List<StateOption> options) {
@Nullable String rangeUnit, @Nullable String pattern, boolean readOnly,
@Nullable List<StateOption> options) {
this.minimum = minimum;
this.maximum = maximum;
this.step = step;
this.rangeUnit = rangeUnit;
this.pattern = pattern;
this.readOnly = readOnly;
this.options = options == null ? List.of() : Collections.unmodifiableList(options);
Expand Down Expand Up @@ -82,6 +86,15 @@ protected StateDescription(@Nullable BigDecimal minimum, @Nullable BigDecimal ma
return step;
}

/**
* Returns the unit that applies to the min, max and step
*
* @return range unit
*/
public @Nullable String getRangeUnit() {
return rangeUnit;
}

/**
* Returns the pattern to render the state to a string.
*
Expand Down Expand Up @@ -119,6 +132,7 @@ public int hashCode() {
result = prime * result + (minimum != null ? minimum.hashCode() : 0);
result = prime * result + (maximum != null ? maximum.hashCode() : 0);
result = prime * result + (step != null ? step.hashCode() : 0);
result = prime * result + (rangeUnit != null ? rangeUnit.hashCode() : 0);
result = prime * result + (pattern != null ? pattern.hashCode() : 0);
result = prime * result + (readOnly ? 1231 : 1237);
result = prime * result + options.hashCode();
Expand All @@ -138,14 +152,15 @@ public boolean equals(@Nullable Object obj) {
}
StateDescription other = (StateDescription) obj;
return Objects.equals(minimum, other.minimum) && Objects.equals(maximum, other.maximum)
&& Objects.equals(step, other.step) && Objects.equals(pattern, other.pattern)
&& readOnly == other.readOnly //
&& Objects.equals(step, other.step) && Objects.equals(rangeUnit, other.rangeUnit)
&& Objects.equals(pattern, other.pattern) && readOnly == other.readOnly //
&& options.equals(other.options);
}

@Override
public String toString() {
return "StateDescription [minimum=" + minimum + ", maximum=" + maximum + ", step=" + step + ", pattern="
+ pattern + ", readOnly=" + readOnly + ", channelStateOptions=" + options + "]";
return "StateDescription [minimum=" + minimum + ", maximum=" + maximum + ", step=" + step + ", rangeUnit="
+ rangeUnit + ", pattern=" + pattern + ", readOnly=" + readOnly + ", channelStateOptions=" + options
+ "]";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ public interface StateDescriptionFragment {
@Nullable
BigDecimal getStep();

/**
* Returns the unit that applies to the min, max and step
*
* @return range unit
*/
@Nullable
String getRangeUnit();

/**
* Returns the pattern to render the state to a string.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class StateDescriptionFragmentBuilder {
private @Nullable BigDecimal minimum;
private @Nullable BigDecimal maximum;
private @Nullable BigDecimal step;
private @Nullable String rangeUnit;
private @Nullable String pattern;
private @Nullable Boolean readOnly;
private @Nullable List<StateOption> options;
Expand All @@ -43,6 +44,7 @@ private StateDescriptionFragmentBuilder(StateDescriptionFragment fragment) {
this.minimum = fragment.getMinimum();
this.maximum = fragment.getMaximum();
this.step = fragment.getStep();
this.rangeUnit = fragment.getRangeUnit();
this.pattern = fragment.getPattern();
this.readOnly = fragment.isReadOnly();
final List<StateOption> stateOptions = fragment.getOptions();
Expand All @@ -55,6 +57,7 @@ private StateDescriptionFragmentBuilder(StateDescription legacy) {
this.minimum = legacy.getMinimum();
this.maximum = legacy.getMaximum();
this.step = legacy.getStep();
this.rangeUnit = legacy.getRangeUnit();
this.pattern = legacy.getPattern();
this.readOnly = Boolean.valueOf(legacy.isReadOnly());
if (!legacy.getOptions().isEmpty()) {
Expand Down Expand Up @@ -100,7 +103,7 @@ public static StateDescriptionFragmentBuilder create(StateDescription legacy) {
*/
@SuppressWarnings("deprecation")
public StateDescriptionFragment build() {
return new StateDescriptionFragmentImpl(minimum, maximum, step, pattern, readOnly, options);
return new StateDescriptionFragmentImpl(minimum, maximum, step, rangeUnit, pattern, readOnly, options);
}

/**
Expand Down Expand Up @@ -136,6 +139,17 @@ public StateDescriptionFragmentBuilder withStep(BigDecimal step) {
return this;
}

/**
* Set the range unit for the resulting {@link StateDescriptionFragment}.
*
* @param rangeUnit the range unit for the resulting {@link StateDescriptionFragment}.
* @return this builder.
*/
public StateDescriptionFragmentBuilder withRangeUnit(String rangeUnit) {
this.rangeUnit = rangeUnit;
return this;
}

/**
* Set the pattern for the resulting {@link StateDescriptionFragment}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public void testFragment() throws Exception {
metadataConfig.put("min", 18.5);
metadataConfig.put("max", "34");
metadataConfig.put("step", 3);
metadataConfig.put("rangeUnit", "°C");
metadataConfig.put("readOnly", "true");
metadataConfig.put("options", "OPTION1,OPTION2 , 3 =Option 3 ,\"4=4\"=\" Option=4 \" ");
Metadata metadata = new Metadata(metadataKey, "N/A", metadataConfig);
Expand All @@ -106,6 +107,7 @@ public void testFragment() throws Exception {
assertEquals(new BigDecimal(18.5), stateDescriptionFragment.getMinimum());
assertEquals(new BigDecimal(34), stateDescriptionFragment.getMaximum());
assertEquals(new BigDecimal(3), stateDescriptionFragment.getStep());
assertEquals("°C", stateDescriptionFragment.getRangeUnit());
assertEquals(true, stateDescriptionFragment.isReadOnly());
assertNotNull(stateDescriptionFragment.getOptions());
Iterator<StateOption> it = stateDescriptionFragment.getOptions().iterator();
Expand Down
Loading