Skip to content

Commit

Permalink
Converted Numeric Ruby setting class to Java
Browse files Browse the repository at this point in the history
  • Loading branch information
andsel committed Nov 18, 2024
1 parent dcae6f5 commit ee264f0
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 20 deletions.
39 changes: 20 additions & 19 deletions logstash-core/lib/logstash/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -413,26 +413,27 @@ def coerce(value)
### Specific settings #####

java_import org.logstash.settings.Boolean
java_import org.logstash.settings.Numeric

class Numeric < Coercible
def initialize(name, default = nil, strict = true)
super(name, ::Numeric, default, strict)
end

def coerce(v)
return v if v.is_a?(::Numeric)

# I hate these "exceptions as control flow" idioms
# but Ruby's `"a".to_i => 0` makes it hard to do anything else.
coerced_value = (Integer(v) rescue nil) || (Float(v) rescue nil)

if coerced_value.nil?
raise ArgumentError.new("Failed to coerce value to Numeric. Received #{v} (#{v.class})")
else
coerced_value
end
end
end
# class Numeric < Coercible
# def initialize(name, default = nil, strict = true)
# super(name, ::Numeric, default, strict)
# end
#
# def coerce(v)
# return v if v.is_a?(::Numeric)
#
# # I hate these "exceptions as control flow" idioms
# # but Ruby's `"a".to_i => 0` makes it hard to do anything else.
# coerced_value = (Integer(v) rescue nil) || (Float(v) rescue nil)
#
# if coerced_value.nil?
# raise ArgumentError.new("Failed to coerce value to Numeric. Received #{v} (#{v.class})")
# else
# coerced_value
# end
# end
# end

class Integer < Coercible
def initialize(name, default = nil, strict = true)
Expand Down
4 changes: 3 additions & 1 deletion logstash-core/spec/logstash/settings/numeric_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,21 @@
require "spec_helper"
require "logstash/settings"

# Mirrored in java class org.logstash.settings.Numeric
describe LogStash::Setting::Numeric do
subject { described_class.new("a number", nil, false) }
describe "#set" do
context "when giving a string which doesn't represent a string" do
it "should raise an exception" do
expect { subject.set("not-a-number") }.to raise_error(ArgumentError)
expect { subject.set("not-a-number") }.to raise_error(java.lang.IllegalArgumentException)
end
end
context "when giving a string which represents a " do
context "float" do
it "should coerce that string to the number" do
subject.set("1.1")
expect(subject.value).to eq(1.1)
expect(subject.value).to be_within(0.01).of(1.1)
end
end
context "int" do
Expand Down
55 changes: 55 additions & 0 deletions logstash-core/src/main/java/org/logstash/settings/Numeric.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.logstash.settings;

public class Numeric extends Coercible<Number> {

public Numeric(String name, Number defaultValue) {
super(name, defaultValue, true, noValidator());
}

// constructor used only in tests
public Numeric(String name, Number defaultValue, boolean strict) {
super(name, defaultValue, strict, noValidator());
}

@Override
public Number coerce(Object obj) {
if (obj instanceof Number) {
return (Number) obj;
}
try {
return Integer.parseInt(obj.toString());
} catch (NumberFormatException e) {
// ugly flow control
}
try {
return Float.parseFloat(obj.toString());
} catch (NumberFormatException e) {
// ugly flow control
}

// no integer neither float parsing succeed, invalid coercion
throw new IllegalArgumentException(coercionFailureMessage(obj));
}

private String coercionFailureMessage(Object obj) {
return String.format("Failed to coerce value to Numeric. Received %s (%s)", obj, obj.getClass());
}
}
56 changes: 56 additions & 0 deletions logstash-core/src/test/java/org/logstash/settings/NumericTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.logstash.settings;

import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.*;

// Mirrored from spec/logstash/settings/numeric_spec.rb
public class NumericTest {

private Numeric sut;

@Before
public void setUp() {
sut = new Numeric("a number", null, false);
}

@Test(expected = IllegalArgumentException.class)
public void givenValueThatIsNotStringWhenSetIsInvokedThrowsException() {
sut.set("not-a-number");
}

@Test
public void givenValueStringThatRepresentFloatWhenSetIsInvokedShouldCoerceThatStringToTheNumber() {
sut.set("1.1");

float value = (Float) sut.value();
assertEquals(1.1f, value, 0.001);
}

@Test
public void givenValueStringThatRepresentIntegerWhenSetIsInvokedShouldCoerceThatStringToTheNumber() {
sut.set("1");

int value = (Integer) sut.value();
assertEquals(1, value);
}
}

0 comments on commit ee264f0

Please sign in to comment.