unitsofmeasurement / unit-api Goto Github PK
View Code? Open in Web Editor NEWUnits of Measurement API
Home Page: http://unitsofmeasurement.github.io/unit-api/
License: Other
Units of Measurement API
Home Page: http://unitsofmeasurement.github.io/unit-api/
License: Other
Especially in the JavaDoc of SI Base Quantities the upcoming changes to the SI should have an impact.
Right now the gh-pages branch resulting in http://unitsofmeasurement.github.io/unit-api/ has a basic out-of-the-box L&F that does not match the rest of the site.
We should better integrate it with the rest of the UoM site.
As discussed it seems a useful SPI feature to discover available
Quantity
implementationsPrefix
implementationsQuick Facts
Unit
must hold an instance of UnitConverter
.UnitConverters
represent transformations.UnitConverters
allow composition, such that composing 2 UnitConverters
is equivalent to composing their transformation functions.UnitConverters
of same type can be equivalent but are not in general, e.g. they may not be equivalent because of different prefix.Suppose we have UnitConverter
types A,B,C.
Let S be the set of UnitConverter
types available.
S:= {A,B,C}
Now if we pick any x
and any y
from S
we need to know
x
commutes with y
, such that a composition x.y is equivalent to y.xx.y
-> x
or x.y
-> y
or similar.Given this information we are ready to state a Word Problem
[1] for any given pair of Units, for example:
Suppose we know A commutes with B, but C does not commute with any other
A.B == B.A
A.C != C.A
B.C != C.B
Suppose we know C composes with C, such that C.C can be simplified to another C
C.C -> C
Suppose we have a UnitConverter p
created by composition of types A, B and C (namely a0, b0 and c0).
p:= b0.a0.c0 (with type composition B.A.C)
Suppose we have a UnitConverter q
created by another composition of types A, B and C (namely a2, b2, c1 and c2).
q:= a2.b2.c1.c2 (with type composition A.B.C.C)
We would then apply Term Rewriting
rules to the type compositions of p
and q
until we find that these are equivalent (or not). Ideally we have such rules that produce a normal form
.
p: B.A.C -> A.B.C
q: A.B.C.C -> A.B.C
Given
p: a0.b0.c0
q: a2.b2.(c1.c2)
then p
is-equivalent-to q
, only if all these hold true
a0 is-equivalent-to a2
b0 is-equivalent-to b2
c0 is-equivalent-to c1.c2
If the Term Rewriting
rules are carefully designed to always produce a normal form
, then the Unit-1 is-equivalent-to Unit-2 problem is decidable. Otherwise it's not for the general case.
[1] https://en.wikipedia.org/wiki/Word_problem_(mathematics)
Needs #39
Update headers to JSR 385.
As a consumer of this API I find it frustrating that I have to propagate extra references just to create a quantity of a given unit. I would much prefer to only have to pass around instances of Unit
to be able to actually work with that unit in a useful way.
I find it strange that the QuantityFactory
interface need exist at all. Why is there no Unit.getQuantity(Number)
method instead? Perhaps I am missing some sensible and important reason but I think the reason for this omission at least deserves some documentation.
This issues list some Javadoc statements that may need to be fixed.
Javadoc said "Return a factory for this Quantity". I think that we mean "Returns a factory for the given Quantity type". Also the javadoc for the @param
tag should be "the quantity type".
Javadoc said "Returns the product of this Quantity divided by the Quantity specified". I guess that we mean "Returns the quotient ...".
Javadoc for @return
tag said "the given system of units". I think that we mean "the system of units for the given name".
UnitFormat.label(String)
said that it throws an IllegalArgumentException
for illegal symbol, but Unit.alternate(String)
does not said what happen in such case. I presume that in the @throws
tag, the "if the specified symbol is already associated to a different unit" statement could be replaced by "if the specified symbol is not valid or is already associated to a different unit".
Parses a portion of the specified CharSequence from the specified position to produce an object.
Should be "... to produde a quantity." in both cases
JSR-275 included a CompoundUnit
, see http://grepcode.com/file/repo1.maven.org/maven2/net.java.dev.jsr-275/jsr-275/1.0-beta-2/javax/measure/unit/CompoundUnit.java
Via Unit.compound(Unit)
a chain of units could be created like "2 years and 3 months". In a similar way as JSR 310 https://docs.oracle.com/javase/8/docs/api/java/time/temporal/TemporalAmount.html allows for temporal amounts. Or the minor/major aspects of JSR 354.
Requires #17
Based on input and concerns by @desruisseaux in #83 please allow me to cast another vote to clarify how we offer Prefix
retrieval from SystemOfUnitsService
?
Actually DefaultSystemOfUnitsService in the RI implementing the interface is of no value, because all the implementations like SISystemService in si-units have to do the same because it's enforced by the interface. Even if (in this case the RI already defines the only "SI Prefix") the module does not define its own prefixes.
Either the RI must get an AbstractSystemOfUnitsService
similar to AbstractSystemOfUnits, allowing all RI-based modules to derive from it, or the one-liner could go directly into SystemOfUnitsService
as default method. Those can always be overriden by implementations that do not rely on enum-based prefixes, so there's nothing lost, but no implementation that uses enums would need any boiler-plate code. It is just a single line of code that every implementation can override if it has to.
Similar to UnitFormat QuantityFormat
should also define a method isLocaleSensitive()
.
Clarify the behavior of Q₁ + Q₂
or Q * n
(with n a unitless number) when the unit of measurement of Q
, Q₁
or Q₂
is "shifted". Example of shifted units are:
Taking temperature in °C as an example, addition can happen in at least two different contexts:
In the T₁ + T₂ case, both quantities must be converted to K before addition. So 20°C + 10°C = 303.15°C because T₂ = 283.15 K. In the T + ΔT case, 10°C is an increment (ΔT). So in this later case 20°C + 10°C = 30°C.
In current API, there is no way to know if a number is an absolute quantity or an increment. So there is no way to know if we are in the T₁ + T₂ case or in the T + ΔT case. If we want to differentiate those quantities, we may need to:
UnitConverter
: deltaConvert(double)
, which convert the given value without applying the offset. This is similar to deltaTransform
in java.awt.geom.AffineTransform
.Increment<Q extends Quantity<Q>>
.M₁ + M₂
or M * n
, implementation SHALL do the following steps at least conceptually (implementations are allowed to avoid conversions in some cases provided that the numerical result is the same):
Quantity
instances shall be done with UnitConverter.convert(…)
.Increment
instances shall be done with UnitConverter.deltaConvert(…)
.Quantity
+ Quantity
= Quantity
Quantity
+ Increment
= Quantity
Increment
+ Quantity
= Quantity
Increment
+ Increment
= Increment
Quantity
* n = Quantity
Increment
* n = Increment
UnitConverter.convert(…)
if the result type is Quantity
.UnitConverter.deltaConvert(…)
if the result type is Increment
.Based on discussions in #85 and hints, we may consider offering default prefixes like MetricPrefix
or BinaryPrefix
in the API, what should make up the Prefix
?
Currently Prefix among String methods declares
/**
* Returns the corresponding {@link UnitConverter}.
*
* @return the unit converter.
*/
public UnitConverter getConverter();
While the implementations of UnitConverter like RationalConverter or MultiplyConverter are not exactly rocket-science, pulling them into the API would blow it up quite significantly. And although V2 aims at Java SE we should not outrule very special converters in specific environments.
So the question is, does the Prefix need a UnitConverter
or would a member variable like value
or factor
be sufficient?
The old BinaryPrefix in uom-lib-common retrofitted as an enum
now, too shows how this may look like in the API if we went for it. I am not casting a vote yet, I am unbiased and could see it in either place.
After VersionEye has gone offline, remove all badges related to it.
The Converter.isLinear()
definition given in Javadoc basically restricts "linear" conversions to this formula:
y = a*x
The definition given in Converter.isLinear()
does not allow the following formula, despite that formula being usually considered linear too:
y = a*x + b
So conversions between Celsius and Kelvin (or between Celsius and Fahrenheit) are not linear according the definition given in Converter.isLinear()
javadoc, which I found surprising. It seems to me that the "isLinear" name is not appropriate for that method. Maybe "isScale" would have been more accurate.
Needs #95
Similar to Indriya the build configuration should be changed to Circle-CI 2.0
The Maven badge on Heroku is constantly broken.
Use something else like Shields.io
Right now the API defines only ParserException
for many errors in the context of parsing or formatting. Sometimes the information available does not meet all arguments ParserException
may take like the exact position of a parsing error. If a problem occurs when formatting, ParserException sounds a bit misleading. Ideally a format-related but more general purpose exception should be introduced. Something like MeasurementFormatException
or similar. The current ParserException
could extend such exception.
Also see #46
Hello,
it would be really nice if the API implements Serializable so that Quantity and Unit can be transfered over the wire
Should the API keep CLDC 8 (Java SE 7) as the minimum version in future, or jump to SE 8 giving it a few advantages like default
methods in interfaces or static constants where applicable on an interface, not just classes?
Loosely following patterns by JSR 374 (https://github.com/json-p/api-ri/blob/master/api/src/main/jdk9/module-info.java and profiles in https://github.com/json-p/api-ri/blob/master/pom.xml) we should add a module (based on JSR 374 it would be "java.measure") and module-info for Java 9 builds.
Effectively releasing such build or any additional Java 9/Jigsaw support will require a MR1 of JSR 363.
Some dependencies are outdated, update them.
Also see unitsofmeasurement/indriya#25 the Multi-Release JAR should be available for the API. If the API JAR is built with Java 9 in a traditional way, it ends up with JVM Version 53
, not compatible with Java 8 (V 52) any more. Ideally the API should still be at least Java 8 compatible with module-info and other Java 9 or 10 features in the correct structure.
A rather generic ParserException
can be found at least in JDK Nashorn, but otherwise both the JDK and other JSRs either call it ParseException
(like java.text.ParseException
) or *ParseException
(like MonetaryParseException
, DateTimeParseException
, etc.)
It is not the most urgent case, but with other proposals like #39 that also would require adding a new name and deprecate the old one, it's worth do mention this as well. A new exception could be called MeasurementParseException
.
Since both Quantity
and Unit
are mandatory core parts and first class citizens of the API, formatting should also be offered for a Quantity
, not just its Unit
part.
https://github.com/unitsofmeasurement/unit-ri/blob/master/src/main/java/tec/units/ri/format/QuantityFormat.java
or its Java SE equivalent are part of the official implementations. There is not a great deal in making an abstract base class or interface available for Quantity as well.
In addition a minor SPI change would require either a QuantityFormatService
or potentially a combined FormatService
providing access to both of them.
At the moment at least
/**
* Returns the quotient of this unit with the one specified.
*
* @param that
* the unit divisor.
* @return <code>this.multiply(that.inverse())</code>
*/
@Override
public final Unit<?> divide(Unit<?> that) {
return this.multiply(that.inverse());
}
/**
* Indicates if this unit belongs to the set of coherent SI units (unscaled SI units).
*
* The base and coherent derived units of the SI form a coherent set, designated the set of coherent SI units. The word coherent is used here in the
* following sense: when coherent units are used, equations between the numerical values of quantities take exactly the same form as the equations
* between the quantities themselves. Thus if only units from a coherent set are used, conversion factors between units are never required.
*
* @return <code>equals(toSystemUnit())</code>
*/
@Override
public boolean isSystemUnit() {
Unit<Q> si = this.toSystemUnit();
return (this == si) || this.equals(si);
}
in AbstractUnit
have no calls or dependency on a concrete implementation class.
Like parts of the JDK (e.g. java.time.temporal.TemporalAmount
) do in similar cases, these methods could be implemented as default
in the Unit
interface.
Currently SystemOfUnitsService returns Collection<Prefix> getPrefixes(String name);
as of #81.
Let's try to retrieve it using the enum class (e.g. MetricPrefix) directly, so something like return Collections.<Prefix>unmodifiableSet(EnumSet.allOf(MetricPrefix.class));
would take the Class
of a particular Prefix
implementation. If we used a default
method in the API, every Prefix
should be based on enums, otherwise we may leave that to implementations like Indriya.
In Unit-API development branch, some default method implementations have been added in the interfaces. I suggest to do so only when the default implementation can fulfill the method contract. In particular:
UnitConverter.isIdentity()
should not return false
by default. The method contract said that a value of false
means that the unit converter is not identity. The default method can hardly detect that by itself.UnitConverter.isLinear()
should not return isIdentity()
by default. This would be okay only when this method returns true
. In the vast majority of cases, this default method would return false
because the converter is not the identity one, but it still linear.Note that the above does not necessarily apply to AbstractConverter
in the reference implementation. In that later case, the strategy to define those default methods in an abstract class is an implementation choice. Since the person who define AbstractConverter
is the same that the one who define the concrete classes on top of it, we can presume that (s)he know what (s)he is doing. But in the Unit-API case, the group defining UnitConverter
is not the same than the group who will implement it.
MetricPrefix and BinaryPrefix should get a higher code coverage.
The new API method isLocaleSensitive() in QuantityFormat is declared as default. Since 2.0 is based on Java SE 8 and a majority of implementations are not locale-sensitive, we should also consider that for UnitFormat.
Use a Java 8+ default
method for UnitConverter.isLinear()
and isIdentity()
.
If we want cross-implementation interoperability, we may need to define the behavior of Dimension.equals(Object)
. It would be needed because two Unit
instances are considered convertible if all their dimensions are equal. One possible approach would be to normalize dimension symbols (L
for length, T
for time, etc.) and require Dimension.equals(Object)
to compare the symbols. But we could also choose that allowing mix of different Dimension
implementation is not a goal, which is all-right (I just don't know if it was a conscientious decision or an accident).
The draft of QuantityFormat
is based on earlier implementation only classes for Java SE. Therefore it uses java.text.ParsePosition
. Should the API reference java.text
although some environments, at least Java ME Embedded do not support it, or shall we no longer care about ME in this version of the API?
Based on #41 the other profiles in https://github.com/unitsofmeasurement/unit-api/blob/master/pom.xml (to create smaller JARs according to profiles from the Spec) should also be able to expose a module like java.measure.core
or similar to distinguish them from other modules.
At the moment these are subsets exposing the relevant packages only and we don't aim to make the "Full Profile" a collection of these modules (though Jigsaw technically would allow that)
Add dependency badge similar to RI, etc.
Would it make sense to have Prefix
as a first class citizen, at least in the SPI similar to what UCAR (much of it evolved from JSR 108) did with: https://github.com/ctrueden/ucar-units/blob/master/src/main/java/ucar/units/Prefix.java?
See https://about.sonarcloud.io/news/2016/09/01/sonarqubedotcom-open-to-aynone.html Either via Maven or CircleCI (if possible similar to Travis examples) the project should be analyzed.
/**
* Convenient method equivalent to {@link #to(javax.measure.Unit) to(this.getUnit().toSystemUnit())}.
*
* @return this quantity or a new quantity equivalent to this quantity stated in SI units.
* @throws ArithmeticException
* if the result is inexact and the quotient has a non-terminating decimal expansion.
*/
public Quantity<Q> toSystemUnit() {
return to(this.getUnit().getSystemUnit());
}
QuantityFormat
adds new formatting options in V2, the default out-of-the-box toString()
implementation in AbstractQuantity
: /**
* Returns the <code>String</code> representation of this quantity. The string produced for a given quantity is always the same; it is not affected
* by locale. This means that it can be used as a canonical string representation for exchanging quantity, or as a key for a Hashtable, etc.
* Locale-sensitive quantity formatting and parsing is handled by the {@link MeasurementFormat} class and its subclasses.
*
* @return <code>UnitFormat.getInternational().format(this)</code>
*/
@Override
public String toString() {
return String.valueOf(getValue()) + " " + String.valueOf(getUnit());
}
Is not likely to change, so we could also offer it on an API level.
At the moment the Unit
interface defines alternate()
or transform()
methods but annotate() is only exposed via the AbstractUnit
base class of implementations. Unless it is too little-used and this is meant to be a status-quo, could it also be added to the Unit
interface from a future version?
The intent of Quantity#inverse()
and Unit#inverse()
methods might be confused with meaning the 'Additive Inverse'.
In math terminology the term 'inverse' can be applied to any function, without being specific.
The API currently uses inverse()
as the 'Multiplicative Inverse', but is not clear about this within the java-doc.
If there's any chance to improve the API, I'd suggest:
Quantity#negate()
as the 'Additive Inverse' (no change in Unit)Quantity#inverse()
with Quantity#reciprocal()
as the 'Multiplicative Inverse'Unit#inverse()
with Unit#reciprocal()
as the 'Multiplicative Inverse'Cheers, Andi!
Would it make sense to add the Level
quantity, currently in systems-quantity here under the quantity
package? As unitsofmeasurement/si-units#47 raises a need to factor it out of uom-systems because the NonSI
class is meant to complement SI
in si-units for Non-SI units accepted with the SI, we should at least move Level
to si-quantity, so the question is, whether it makes sense or wastes space to put it into the API? Compared to other new API elements it does not seem to be massive (adding 320 bytes
to the JAR) and quantity
is an optional package that very resource constraint environments could leave out.
As the new API adds QuantityFormat
, there could be two approaches in the SPI.
Please vote for your preference.
SystemOfUnit.getUnit(Class<Q> quantityType)
does not said what to do if no unit is found for the given quantity type. Should the method returns null
or throw an exception?
Needs #65
The Unit.prefix()
method does not seem to have parameters or return values documented.
At least JIRA is still mentioned on java.net.
Update this reference to GitHub and check for possible other links to java.net
Hey guys, I saw that the API are not using the last version of JUnit and as improvement process, I would update the JUnit library.
I can start with the API and after the others projects like indriya
While most Prefix
implementations use a Java enum
, its values()
method is only available in the actual implementation. Can we add a method to Prefix that works like SystemOfUnits.getUnits()
?
For enum based implementations, it seems rather straightforward via:
return Collections.<Prefix>unmodifiableSet(EnumSet.allOf(MetricPrefix.class));
see https://stackoverflow.com/questions/6528570/converting-from-enumseta-to-setb-when-a-inherits-from-b
Hopefully easier vote on how to call this method?
Similar to UnitFormat
version 2 should also have QuantityFormat
in the API.
Currently SystemOfUnits allows to acces the default (base) unit like:
SystemOfUnits metricSystem = ServiceProvider.current().getSystemOfUnitsService().
getSystemOfUnits();
Unit<Length> metre = metricSystem.getUnit(Length.class);
For other units it is necessary to look it up from the set of units
Unit<?> metre;
SystemOfUnits metricSystem = ServiceProvider.current().getSystemOfUnitsService().
getSystemOfUnits();
for (Unit u: metricSystem.getUnits()) {
if ("m".equals(u.getSymbol()) {
metre = u;
break;
}
}
Although this for
loop may be easier and shorter with Lambdas would it make sense to add a method like <? extends Unit<?>> getUnit(String key)
to SystemOfUnits
? Allowing to access a Unit
via its String
representation. Whether symbol, name or label (what's used by toString()
) is a separate question, first we should decide, if we want this extra method in the 2.0 API.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.