From 4395fa57c434b7d64964b33cfdcaa5e9528e420e Mon Sep 17 00:00:00 2001
From: Kai Brassel <mail@khbrassel.de>
Date: Mon, 6 Sep 2021 12:21:53 +0200
Subject: [PATCH] Added services methods usable in Sirius scripts.

---
 .../cityunits/model/Services.java             | 103 ++++++++++++++++++
 .../META-INF/MANIFEST.MF                      |   3 +-
 .../cityunits/tests/ServicesTest.java         |  31 ++++++
 3 files changed, 136 insertions(+), 1 deletion(-)
 create mode 100644 de.hftstuttgart.cityunits.model/src/de/hftstuttgart/cityunits/model/Services.java
 create mode 100644 de.hftstuttgart.cityunits.tests/src/de/hftstuttgart/cityunits/tests/ServicesTest.java

diff --git a/de.hftstuttgart.cityunits.model/src/de/hftstuttgart/cityunits/model/Services.java b/de.hftstuttgart.cityunits.model/src/de/hftstuttgart/cityunits/model/Services.java
new file mode 100644
index 0000000..e0bb353
--- /dev/null
+++ b/de.hftstuttgart.cityunits.model/src/de/hftstuttgart/cityunits/model/Services.java
@@ -0,0 +1,103 @@
+package de.hftstuttgart.cityunits.model;
+
+import org.eclipse.emf.common.util.EMap;
+import org.eclipse.emf.ecore.EAnnotation;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EAttribute;
+
+/**
+ * The services class used by VSM (Sirius).
+ */
+public class Services {
+
+	/**
+	 * Return unit string from given string representation of a Quantity. The
+	 * substring before the first blank in the argument is regarded as the value of
+	 * the quantity and the substring after that blank as its unit. Note, that unit
+	 * part or value part or both can be missing, implying that no blank is present.
+	 *
+	 * @param someEObject (required to make this method available for Sirius scripts)
+	 * @param quantity String representing a quantity 
+	 * @return unit substring of given string if present, otherwise the empty string 
+	 */
+	public String extractUnit(EObject someEObject, String quantity) {
+		String quant = quantity.trim();
+		int i = quant.indexOf(' ');
+		if (i < 0) {
+			try {
+				Double.parseDouble(quant);
+				return "";
+			} catch (Exception ex) {
+				// quant does not contain a number: should be unit
+				return quant;
+			}
+		} else {
+			return quant.substring(i + 1);
+		}
+	}
+
+	/**
+	 * Return value from given string representation of a Quantity as string. The
+	 * substring before the first blank in the argument is regarded as the value of
+	 * the quantity and the substring after that blank as its unit. Note, that value
+	 * part or unit part or both can be missing, implying that no blank is present.
+	 *
+	 * @param someEObject (required to make this method available for Sirius scripts) 
+	 * @param quantity String representing a quantity 
+	 * @return numerical value of given quantity as string if present, otherwise the empty string 
+	 */
+	public String extractValue(EObject someEObject, String quantity) {
+		String quant = quantity.trim();
+		int i = quant.indexOf(' ');
+		if (i < 0) {
+			try {
+				Double.parseDouble(quant);
+				return quant;
+			} catch (Exception ex) {
+				// quant does not contain a number: should be unit
+				return "";
+			}
+		} else {
+			return quant.substring(0, i);
+		}
+	}
+
+	
+	/**
+	 * If <code>newValue</code> is a valid number not within the range defined by annotation 
+	 * http://www.hft-stuttgart.de/UomQuantities, adapt it to the minimum or maximum value of the range
+	 * and return its string. Otherwise (no valid number, no annotation or missing (valid) min/max numbers
+	 * in the annotation), rust return the given <code>newValue</code> unchanged.
+	 * 
+ 	 * @param eAttribute a numerical Ecore attribute  
+ 	 * @param newValue String with a new value for the given attribute
+ 	 * @return String with the new value for the given attribute, possibly adapted to the declared range.
+ 	 */
+ 	public String minMaxAnnotation(EObject eAttribute, String newValue) {
+		double value;
+		try {
+			value = Double.parseDouble(newValue);
+		} catch (Exception ex) {
+			return newValue;
+		}
+
+		EAttribute attr = (EAttribute) eAttribute;
+		EAnnotation annot = attr.getEAnnotation("http://www.hft-stuttgart.de/UomQuantities");
+		if (annot == null) {
+			return newValue;
+		}
+
+		EMap<String, String> details = annot.getDetails();
+		try {
+			value = Math.max(Double.parseDouble(details.get("min")), value);
+		} catch (Exception ex) {
+			; // do not change value
+		}
+		try {
+			value = Math.min(Double.parseDouble(details.get("max")), value);
+		} catch (Exception ex) {
+			; // do not change value
+		}
+		return Double.toString(value);
+	}
+}
diff --git a/de.hftstuttgart.cityunits.tests/META-INF/MANIFEST.MF b/de.hftstuttgart.cityunits.tests/META-INF/MANIFEST.MF
index 4842d96..d019b90 100644
--- a/de.hftstuttgart.cityunits.tests/META-INF/MANIFEST.MF
+++ b/de.hftstuttgart.cityunits.tests/META-INF/MANIFEST.MF
@@ -9,4 +9,5 @@ Import-Package: de.hftstuttgart.cityunits.model,
  org.junit.jupiter.api;version="5.6.0"
 Require-Bundle: javax.measure.unit-api,
  tech.units.indriya,
- uom-lib-common;bundle-version="[2.1.0,3.0.0)"
+ uom-lib-common;bundle-version="[2.1.0,3.0.0)",
+ org.eclipse.emf.ecore
diff --git a/de.hftstuttgart.cityunits.tests/src/de/hftstuttgart/cityunits/tests/ServicesTest.java b/de.hftstuttgart.cityunits.tests/src/de/hftstuttgart/cityunits/tests/ServicesTest.java
new file mode 100644
index 0000000..a031a24
--- /dev/null
+++ b/de.hftstuttgart.cityunits.tests/src/de/hftstuttgart/cityunits/tests/ServicesTest.java
@@ -0,0 +1,31 @@
+package de.hftstuttgart.cityunits.tests;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.eclipse.emf.ecore.EObject;
+import org.junit.jupiter.api.Test;
+
+import de.hftstuttgart.cityunits.model.Services;
+
+
+class ServicesTest {
+
+	@Test
+	void testExtractValue() {
+		var services = new Services();
+		assertEquals("1.23", services.extractValue((EObject)null, "1.23"), "Wrong value extraction from quantity!");
+		assertEquals("1", services.extractValue((EObject)null, "1"), "Wrong value extraction from quantity!");
+		assertEquals("2.34", services.extractValue((EObject)null, "2.34 km"), "Wrong value extraction from quantity!");
+		assertEquals("wrong", services.extractValue((EObject)null, "wrong number km"), "Wrong value extraction from quantity!");
+		assertEquals("", services.extractValue((EObject)null, ""), "Empty quantity must return empty value!");
+	}
+
+	@Test
+	void testExtractUnit() {
+		var services = new Services();
+		assertEquals("kg", services.extractUnit((EObject)null, "kg"), "Wrong value extraction from quantity!");
+		assertEquals("km", services.extractUnit((EObject)null, "2.34 km"), "Wrong value extraction from quantity!");
+		assertEquals("wrong unit", services.extractUnit((EObject)null, "12 wrong unit"), "Wrong unit extraction from quantity!");
+		assertEquals("", services.extractUnit((EObject)null, ""), "Empty quantity must return empty unit!");
+	}
+}
-- 
GitLab