Commit b2abc6df authored by Kai-Holger Brassel's avatar Kai-Holger Brassel
Browse files

First public version as of Verena Weilers Dissertation

parent 2c40014f
No related merge requests found
Showing with 376 additions and 0 deletions
+376 -0
package de.hftstuttgart.units.ui.renderer;
import org.eclipse.core.databinding.property.value.IValueProperty;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
import org.eclipse.emf.ecp.view.spi.model.VControl;
import org.eclipse.emf.ecp.view.spi.model.VElement;
import org.eclipse.emfforms.spi.common.report.ReportService;
import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedException;
import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedReport;
import org.eclipse.emfforms.spi.core.services.databinding.EMFFormsDatabinding;
import org.eclipse.emfforms.spi.swt.core.AbstractSWTRenderer;
import org.eclipse.emfforms.spi.swt.core.di.EMFFormsDIRendererService;
import de.hftstuttgart.units.NullableQuantity;
/**
* QuantityRendererService which provides the QuantityRenderer.
*
* @author Kai Brassel
*
*/
public class QuantityControlRendererService implements EMFFormsDIRendererService<VControl> {
private EMFFormsDatabinding databindingService;
private ReportService reportService;
/**
* Called by the initializer to set the EMFFormsDatabinding.
*
* @param databindingService The EMFFormsDatabinding
*/
protected void setEMFFormsDatabinding(EMFFormsDatabinding databindingService) {
this.databindingService = databindingService;
}
/**
* Called by the initializer to set the ReportService.
*
* @param reportService The ReportService
*/
protected void setReportService(ReportService reportService) {
this.reportService = reportService;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emfforms.spi.swt.core.di.EMFFormsDIRendererService#isApplicable(VElement,ViewModelContext)
*/
@Override
public double isApplicable(VElement vElement, ViewModelContext viewModelContext) {
if (!VControl.class.isInstance(vElement)) {
return NOT_APPLICABLE;
}
final VControl control = (VControl) vElement;
if (control.getDomainModelReference() == null) {
return NOT_APPLICABLE;
}
@SuppressWarnings("rawtypes")
IValueProperty valueProperty;
try {
valueProperty = databindingService.getValueProperty(control.getDomainModelReference(),
viewModelContext.getDomainModel());
} catch (final DatabindingFailedException ex) {
reportService.report(new DatabindingFailedReport(ex));
return NOT_APPLICABLE;
}
final EStructuralFeature eStructuralFeature = EStructuralFeature.class.cast(valueProperty.getValueType());
if (eStructuralFeature.getEType().getInstanceClass() == NullableQuantity.class) {
return 9; // 9 - not 10 - to avoid priority clash with multi-valued attributes
}
return NOT_APPLICABLE;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emfforms.spi.swt.core.di.EMFFormsDIRendererService#getRendererClass()
*/
@Override
public Class<? extends AbstractSWTRenderer<VControl>> getRendererClass() {
return QuantityControlRenderer.class;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>de.hftstuttgart.units</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Units
Bundle-SymbolicName: de.hftstuttgart.units
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: HfT Stuttgart
Automatic-Module-Name: de.hftstuttgart.units
Require-Bundle: de.hftstuttgart.indriya.osgiplugin;bundle-version="1.0.0"
Export-Package: de.hftstuttgart.units
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.
package de.hftstuttgart.units;
import javax.measure.Quantity;
/**
* This interface represents the intensity dimension.
*/
public interface Dollar extends Quantity<Dollar>
{
}
\ No newline at end of file
package de.hftstuttgart.units;
import javax.measure.Quantity;
/**
* This interface represents the intensity dimension.
*/
public interface Euro extends Quantity<Euro>
{
}
\ No newline at end of file
package de.hftstuttgart.units;
import javax.measure.Quantity;
/**
* This interface represents the intensity dimension.
*/
public interface Intensity extends Quantity<Intensity>
{
}
\ No newline at end of file
package de.hftstuttgart.units;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
import java.util.Optional;
import javax.measure.Quantity;
import javax.measure.Unit;
import tech.units.indriya.format.SimpleQuantityFormat;
import tech.units.indriya.quantity.Quantities;
/**
* A <code>NullableQuantity</code> wraps a <code>javax.measure.Quantity</code> having
* a numerical value that is either a <code>Double</code>, a <code>Long</code>,
* or <code>null</code>. The latter case represents an unknown numerical
* value of a specific unit. On the other hand, the <code>javax.measure.Unit</code>
* of the quantity is always defined.
*/
public class NullableQuantity {
static {
// TODO Implement specific QuantityFormat to enable custom number format?
// ensure that editing, (de)serialization and default values of units all work
// with the same number format (Decimal point etc.)
Locale.setDefault(Locale.ENGLISH);
// specific additional units for urban simulation like TON (t), PARTS_PER_MILLION (ppm), DECIBEL (dB)
UrbanSimulationUnits.getInstance();
}
public static NullableQuantity create(String str) {
NullableQuantity newNullableQuantity = null;
try {
NumberFormat.getInstance().parse(str);
newNullableQuantity = new NullableQuantity(str);
} catch (final ParseException ex) { // no number value present: create NullQuantity just with unit
try {
NullableQuantity dummy = new NullableQuantity("1 " + str); //$NON-NLS-1$
newNullableQuantity = new NullQuantity(dummy.getUnit());
} catch (final IllegalArgumentException ex1) { // Unit could not be parsed
System.out.println("Unit '" + str + "' could not be parsed!"); //TODO
ex.printStackTrace();
}
} catch (final IllegalArgumentException ex) { // Quantity could not be parsed
System.out.println("Quantity '" + str + "' could not be parsed!"); //TODO
ex.printStackTrace();
}
return newNullableQuantity;
}
public static NullableQuantity create(Number number, Unit<?> unit) {
return number == null ? new NullQuantity(unit) : new NullableQuantity(number, unit);
}
private final Quantity<?> quantity;
private NullableQuantity(String str) {
quantity = Quantities.getQuantity(str);
}
private NullableQuantity(Number number, Unit<?> unit) {
quantity = Quantities.getQuantity(number, unit);
}
/**
* In case of an unknown numerical value of the quantity an empty <code>Optional</code> is returned via subclass.
* @return the wrapped <code>javax.measure.Quantity</code> if its numerical value is present
*/
public Optional<Quantity<?>> getQuantity() {
return Optional.of(quantity);
}
/**
* @return numerical value of the wrapped <code>javax.measure.Quantity</code> if present
*/
public Optional<Number> getNumber() {
return getQuantity().map(Quantity::getValue);
}
public Unit<?> getUnit() {
return quantity.getUnit();
}
@Override
public String toString() {
return SimpleQuantityFormat.getInstance().format(quantity);
}
private static class NullQuantity extends NullableQuantity {
public NullQuantity(Unit<?> unit) {
super(1, unit);
}
public Optional<Quantity<?>> getQuantity() {
return Optional.empty();
}
@Override
public String toString() {
return "<unknown> " + getUnit().toString();
}
}
}
package de.hftstuttgart.units;
import java.math.BigInteger;
import javax.measure.Dimension;
import javax.measure.Quantity;
import javax.measure.Unit;
import javax.measure.quantity.Dimensionless;
import javax.measure.quantity.Mass;
import javax.measure.spi.SystemOfUnits;
import tech.units.indriya.AbstractSystemOfUnits;
import tech.units.indriya.AbstractUnit;
import tech.units.indriya.format.SimpleUnitFormat;
import tech.units.indriya.function.LogConverter;
import tech.units.indriya.function.MultiplyConverter;
import tech.units.indriya.unit.AlternateUnit;
import tech.units.indriya.unit.BaseUnit;
import tech.units.indriya.unit.TransformedUnit;
import tech.units.indriya.unit.UnitDimension;
import tech.units.indriya.unit.Units;
public class UrbanSimulationUnits extends AbstractSystemOfUnits
{
private static final UrbanSimulationUnits INSTANCE = new UrbanSimulationUnits();
@Override
public String getName() {
return getClass().getSimpleName();
}
public static final Unit<Dimensionless> PARTS_PER_MILLION = addUnit(new TransformedUnit<>(AbstractUnit.ONE,
MultiplyConverter.ofRational(BigInteger.ONE, BigInteger.valueOf(1000000))));
public static final Unit<Dimensionless> DECIBEL = addUnit(AbstractUnit.ONE.transform(
new LogConverter(10).inverse().concatenate(MultiplyConverter.ofRational(BigInteger.ONE, BigInteger.TEN))));
public static final Unit<Mass> TON = addUnit(Units.KILOGRAM.multiply(1000));
public static final Unit<Intensity> IRRADIANCE = addUnit(
new AlternateUnit<Intensity>(Units.WATT.divide(Units.SQUARE_METRE), "W/m2"));
// To model costs I added monetary units quick and dirty as SI base units. According to JavaDoc of AbstractUnit,
// monetary units should rather be implemented in an extra type hierarchy below ComparableUnit.
public final static Dimension MONEY_DIMENSION = UnitDimension.parse('M');
public final static Unit<Euro> EURO = new BaseUnit<Euro>("€", MONEY_DIMENSION);
public final static Unit<Dollar> DOLLAR = new BaseUnit<Dollar>("$", MONEY_DIMENSION);
static {
SimpleUnitFormat.getInstance().label(TON, "t");
SimpleUnitFormat.getInstance().label(DECIBEL, "dB");
SimpleUnitFormat.getInstance().label(PARTS_PER_MILLION, "ppm");
SimpleUnitFormat.getInstance().label(EURO, "€");
SimpleUnitFormat.getInstance().label(DOLLAR, "$");
}
/**
* Returns the unique instance of this class.
*
* @return the Units instance.
*/
public static SystemOfUnits getInstance() {
return INSTANCE;
}
/**
* Adds a new unit not mapped to any specified quantity type.
*
* @param unit the unit being added.
* @return <code>unit</code>.
*/
private static <U extends Unit<?>> U addUnit(U unit) {
INSTANCE.units.add(unit);
return unit;
}
/**
* Adds a new unit and maps it to the specified quantity type.
*
* @param unit the unit being added.
* @param type the quantity type.
* @return <code>unit</code>.
*/
private static <U extends AbstractUnit<?>> U addUnit(U unit, Class<? extends Quantity<?>> type) {
INSTANCE.units.add(unit);
INSTANCE.quantityToUnit.put(type, unit);
return unit;
}
}
package de.hftstuttgart.units;
import javax.measure.Quantity;
/**
* Define Volumetric Flow Rate type (basic unit is m^3/s).
*/
public interface VolumetricFlowRate extends Quantity<VolumetricFlowRate>
{
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment