From d243a854f0777d00f2ec7465935548d5c6fa6d17 Mon Sep 17 00:00:00 2001 From: Villu Ruusmann Date: Tue, 1 Oct 2024 19:23:22 +0300 Subject: [PATCH 01/16] Updated version information --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0b4aeedc..3c062397 100644 --- a/README.md +++ b/README.md @@ -36,13 +36,13 @@ Java Class Model API for Predictive Model Markup Language (PMML). JPMML-Model library JAR files (together with accompanying Java source and Javadocs JAR files) are released via [Maven Central Repository](https://repo1.maven.org/maven2/org/jpmml/). -The current version is **1.6.5** (24 June, 2024). +The current version is **1.6.6** (1 October, 2024). ```xml org.jpmml pmml-model - 1.6.5 + 1.6.6 ``` From 014128f19738fc5751e3450e8098853bfd114dfd Mon Sep 17 00:00:00 2001 From: Villu Ruusmann Date: Mon, 11 Nov 2024 11:22:13 +0200 Subject: [PATCH 02/16] Fixed VersionInspector#isElement(Field) utility method --- .../model/visitors/VersionInspector.java | 4 +- .../model/visitors/VersionInspectorTest.java | 41 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 pmml-model/src/test/java/org/jpmml/model/visitors/VersionInspectorTest.java diff --git a/pmml-model/src/main/java/org/jpmml/model/visitors/VersionInspector.java b/pmml-model/src/main/java/org/jpmml/model/visitors/VersionInspector.java index 6962805b..7a5fe652 100644 --- a/pmml-model/src/main/java/org/jpmml/model/visitors/VersionInspector.java +++ b/pmml-model/src/main/java/org/jpmml/model/visitors/VersionInspector.java @@ -11,6 +11,7 @@ import jakarta.xml.bind.annotation.XmlAttribute; import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlElements; import jakarta.xml.bind.annotation.XmlEnumValue; import org.dmg.pmml.Apply; import org.dmg.pmml.PMMLAttributes; @@ -174,7 +175,8 @@ protected boolean isEnumValue(Field field){ static protected boolean isElement(Field field){ XmlElement xmlElement = field.getAnnotation(XmlElement.class); + XmlElements xmlElements = field.getAnnotation(XmlElements.class); - return (xmlElement != null); + return (xmlElement != null) || (xmlElements != null); } } \ No newline at end of file diff --git a/pmml-model/src/test/java/org/jpmml/model/visitors/VersionInspectorTest.java b/pmml-model/src/test/java/org/jpmml/model/visitors/VersionInspectorTest.java new file mode 100644 index 00000000..9c52c7e8 --- /dev/null +++ b/pmml-model/src/test/java/org/jpmml/model/visitors/VersionInspectorTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 Villu Ruusmann + */ +package org.jpmml.model.visitors; + +import java.lang.reflect.Field; + +import org.dmg.pmml.PMMLAttributes; +import org.dmg.pmml.PMMLElements; +import org.dmg.pmml.ResultFeature; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class VersionInspectorTest { + + @Test + public void isAttribute(){ + assertTrue(VersionInspector.isAttribute(PMMLAttributes.OUTPUTFIELD_NAME)); + + assertFalse(VersionInspector.isAttribute(PMMLElements.OUTPUTFIELD_EXTENSIONS)); + } + + @Test + public void isEnumValue() throws NoSuchFieldException { + Field field = ResultFeature.class.getField("PREDICTED_VALUE"); + + assertTrue(VersionInspector.isEnumValue(field)); + + assertFalse(VersionInspector.isEnumValue(PMMLAttributes.OUTPUTFIELD_RESULTFEATURE)); + } + + @Test + public void isElement(){ + assertFalse(VersionInspector.isElement(PMMLAttributes.OUTPUTFIELD_NAME)); + + assertTrue(VersionInspector.isElement(PMMLElements.OUTPUTFIELD_EXTENSIONS)); + assertTrue(VersionInspector.isElement(PMMLElements.OUTPUTFIELD_EXPRESSION)); + } +} \ No newline at end of file From ad20c9ee34c138edc464f2f07cee6aa2d26b88b8 Mon Sep 17 00:00:00 2001 From: Villu Ruusmann Date: Mon, 11 Nov 2024 22:11:13 +0200 Subject: [PATCH 03/16] Added MisplacedElementListException exception class --- .../model/InvalidElementListException.java | 8 ++++++++ .../model/MisplacedElementListException.java | 20 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 pmml-model/src/main/java/org/jpmml/model/MisplacedElementListException.java diff --git a/pmml-model/src/main/java/org/jpmml/model/InvalidElementListException.java b/pmml-model/src/main/java/org/jpmml/model/InvalidElementListException.java index 2514a085..c7e0b96b 100644 --- a/pmml-model/src/main/java/org/jpmml/model/InvalidElementListException.java +++ b/pmml-model/src/main/java/org/jpmml/model/InvalidElementListException.java @@ -9,6 +9,14 @@ public class InvalidElementListException extends InvalidMarkupException { + public InvalidElementListException(String message){ + super(message); + } + + public InvalidElementListException(String message, PMMLObject object){ + super(message, object); + } + public InvalidElementListException(List objects){ super("List of elements " + XPathUtil.formatElement((objects.get(0)).getClass()) + " is not valid", objects.get(0)); } diff --git a/pmml-model/src/main/java/org/jpmml/model/MisplacedElementListException.java b/pmml-model/src/main/java/org/jpmml/model/MisplacedElementListException.java new file mode 100644 index 00000000..230db75c --- /dev/null +++ b/pmml-model/src/main/java/org/jpmml/model/MisplacedElementListException.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 Villu Ruusmann + */ +package org.jpmml.model; + +import java.util.List; + +import org.dmg.pmml.PMMLObject; + +public class MisplacedElementListException extends InvalidElementListException { + + public MisplacedElementListException(List objects){ + super(formatMessage(XPathUtil.formatElement((objects.get(0)).getClass())), objects.get(0)); + } + + static + public String formatMessage(String xPath){ + return "List of elements " + xPath + " is not permitted in this location"; + } +} \ No newline at end of file From dca8b43dd6be1bf734191cde9eb25284df739558 Mon Sep 17 00:00:00 2001 From: Villu Ruusmann Date: Tue, 12 Nov 2024 19:33:01 +0200 Subject: [PATCH 04/16] Fixed the version checking of repeated elements --- .../jpmml/model/visitors/VersionChecker.java | 20 ++++++++++++++-- .../model/visitors/VersionCheckerTest.java | 23 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/pmml-model/src/main/java/org/jpmml/model/visitors/VersionChecker.java b/pmml-model/src/main/java/org/jpmml/model/visitors/VersionChecker.java index 5164ca5a..a164e8cd 100644 --- a/pmml-model/src/main/java/org/jpmml/model/visitors/VersionChecker.java +++ b/pmml-model/src/main/java/org/jpmml/model/visitors/VersionChecker.java @@ -14,11 +14,13 @@ import org.jpmml.model.MarkupException; import org.jpmml.model.MisplacedAttributeException; import org.jpmml.model.MisplacedElementException; +import org.jpmml.model.MisplacedElementListException; import org.jpmml.model.MissingAttributeException; import org.jpmml.model.MissingElementException; import org.jpmml.model.ReflectionUtil; import org.jpmml.model.UnsupportedAttributeException; import org.jpmml.model.UnsupportedElementException; +import org.jpmml.model.UnsupportedElementListException; import org.jpmml.model.annotations.Added; import org.jpmml.model.annotations.Optional; import org.jpmml.model.annotations.Removed; @@ -60,7 +62,14 @@ public void handleAdded(PMMLObject object, AnnotatedElement element, Added added } else if(isElement(field)){ - report(new UnsupportedElementException((PMMLObject)value)); + + if(value instanceof List){ + report(new UnsupportedElementListException((List)value)); + } else + + { + report(new UnsupportedElementException((PMMLObject)value)); + } } else { @@ -90,7 +99,14 @@ public void handleRemoved(PMMLObject object, AnnotatedElement element, Removed r } else if(isElement(field)){ - report(new MisplacedElementException((PMMLObject)value)); + + if(value instanceof List){ + report(new MisplacedElementListException((List)value)); + } else + + { + report(new MisplacedElementException((PMMLObject)value)); + } } else { diff --git a/pmml-model/src/test/java/org/jpmml/model/visitors/VersionCheckerTest.java b/pmml-model/src/test/java/org/jpmml/model/visitors/VersionCheckerTest.java index 9e3be4b0..61374ff8 100644 --- a/pmml-model/src/test/java/org/jpmml/model/visitors/VersionCheckerTest.java +++ b/pmml-model/src/test/java/org/jpmml/model/visitors/VersionCheckerTest.java @@ -11,10 +11,15 @@ import java.util.stream.Collectors; import org.dmg.pmml.Apply; +import org.dmg.pmml.DataType; +import org.dmg.pmml.DerivedField; +import org.dmg.pmml.FieldRef; +import org.dmg.pmml.Interval; import org.dmg.pmml.LocalTransformations; import org.dmg.pmml.MathContext; import org.dmg.pmml.MiningFunction; import org.dmg.pmml.MiningSchema; +import org.dmg.pmml.OpType; import org.dmg.pmml.Output; import org.dmg.pmml.OutputField; import org.dmg.pmml.PMMLFunctions; @@ -26,6 +31,7 @@ import org.dmg.pmml.mining.Segmentation; import org.jpmml.model.MarkupException; import org.jpmml.model.MisplacedElementException; +import org.jpmml.model.MisplacedElementListException; import org.jpmml.model.MissingAttributeException; import org.jpmml.model.MissingElementException; import org.jpmml.model.UnsupportedAttributeException; @@ -56,6 +62,23 @@ public void inspectApply(){ assertExceptions(apply, Version.PMML_4_4, Collections.singleton(UnsupportedAttributeException.class)); } + @Test + public void inspectDerivedField(){ + Interval negativeInterval = new Interval(Interval.Closure.CLOSED_OPEN) + .setLeftMargin(-Double.MAX_VALUE) + .setRightMargin(0d); + + Interval positiveInterval = new Interval(Interval.Closure.OPEN_CLOSED) + .setLeftMargin(0d) + .setRightMargin(Double.MAX_VALUE); + + DerivedField derivedField = new DerivedField("double(x)", OpType.CONTINUOUS, DataType.DOUBLE, new FieldRef("x")) + .addIntervals(negativeInterval, positiveInterval); + + assertExceptions(derivedField, Version.PMML_4_4, Collections.singleton(MisplacedElementListException.class)); + assertExceptions(derivedField, Version.PMML_3_0, Collections.emptySet()); + } + @Test public void inspectMiningModel(){ Segmentation segmentation = new Segmentation() From 568c9a1714bc05581d8ae0be44b914dbbe06e371 Mon Sep 17 00:00:00 2001 From: Villu Ruusmann Date: Wed, 13 Nov 2024 19:51:55 +0200 Subject: [PATCH 05/16] Fixed the formatting of polymorphic elements The XPathUtil#formatElement(Field) and XPathUtil#formatAttribute(Field) utility methods fail with fields that have been declared in intermediate levels of the class hierarchy. --- .../model/InvalidAttributeException.java | 2 +- .../model/MisplacedAttributeException.java | 2 +- .../model/MissingAttributeException.java | 2 +- .../jpmml/model/MissingElementException.java | 2 +- .../model/UnsupportedAttributeException.java | 2 +- .../java/org/jpmml/model/XPathUtilTest.java | 63 +++++++++++++++++++ 6 files changed, 68 insertions(+), 5 deletions(-) diff --git a/pmml-model/src/main/java/org/jpmml/model/InvalidAttributeException.java b/pmml-model/src/main/java/org/jpmml/model/InvalidAttributeException.java index 14b0a597..b9e9243a 100644 --- a/pmml-model/src/main/java/org/jpmml/model/InvalidAttributeException.java +++ b/pmml-model/src/main/java/org/jpmml/model/InvalidAttributeException.java @@ -22,7 +22,7 @@ public InvalidAttributeException(PMMLObject object, Enum value){ } public InvalidAttributeException(PMMLObject object, Field field, Object value){ - super(formatMessage(XPathUtil.formatAttribute(field, value)), object); + super(formatMessage(XPathUtil.formatAttribute(object.getClass(), field, value)), object); } static diff --git a/pmml-model/src/main/java/org/jpmml/model/MisplacedAttributeException.java b/pmml-model/src/main/java/org/jpmml/model/MisplacedAttributeException.java index e1999599..dc5c485c 100644 --- a/pmml-model/src/main/java/org/jpmml/model/MisplacedAttributeException.java +++ b/pmml-model/src/main/java/org/jpmml/model/MisplacedAttributeException.java @@ -14,7 +14,7 @@ public MisplacedAttributeException(PMMLObject object, Enum value){ } public MisplacedAttributeException(PMMLObject object, Field field, Object value){ - super(formatMessage(XPathUtil.formatAttribute(field, value)), object); + super(formatMessage(XPathUtil.formatAttribute(object.getClass(), field, value)), object); } static diff --git a/pmml-model/src/main/java/org/jpmml/model/MissingAttributeException.java b/pmml-model/src/main/java/org/jpmml/model/MissingAttributeException.java index c6599ade..544838db 100644 --- a/pmml-model/src/main/java/org/jpmml/model/MissingAttributeException.java +++ b/pmml-model/src/main/java/org/jpmml/model/MissingAttributeException.java @@ -18,7 +18,7 @@ public MissingAttributeException(String message, PMMLObject context){ } public MissingAttributeException(PMMLObject object, Field field){ - super(formatMessage(XPathUtil.formatElementOrAttribute(field)), object); + super(formatMessage(XPathUtil.formatElementOrAttribute(object.getClass(), field)), object); } static diff --git a/pmml-model/src/main/java/org/jpmml/model/MissingElementException.java b/pmml-model/src/main/java/org/jpmml/model/MissingElementException.java index 3eac41c3..ab5f38e1 100644 --- a/pmml-model/src/main/java/org/jpmml/model/MissingElementException.java +++ b/pmml-model/src/main/java/org/jpmml/model/MissingElementException.java @@ -18,7 +18,7 @@ public MissingElementException(String message, PMMLObject context){ } public MissingElementException(PMMLObject object, Field field){ - super(formatMessage(XPathUtil.formatElementOrAttribute(field)), object); + super(formatMessage(XPathUtil.formatElementOrAttribute(object.getClass(), field)), object); } static diff --git a/pmml-model/src/main/java/org/jpmml/model/UnsupportedAttributeException.java b/pmml-model/src/main/java/org/jpmml/model/UnsupportedAttributeException.java index ed98f546..141d88f9 100644 --- a/pmml-model/src/main/java/org/jpmml/model/UnsupportedAttributeException.java +++ b/pmml-model/src/main/java/org/jpmml/model/UnsupportedAttributeException.java @@ -22,6 +22,6 @@ public UnsupportedAttributeException(PMMLObject object, Enum value){ } public UnsupportedAttributeException(PMMLObject object, Field field, Object value){ - super("Attribute with value " + XPathUtil.formatAttribute(field, value) + " is not supported", object); + super("Attribute with value " + XPathUtil.formatAttribute(object.getClass(), field, value) + " is not supported", object); } } \ No newline at end of file diff --git a/pmml-model/src/test/java/org/jpmml/model/XPathUtilTest.java b/pmml-model/src/test/java/org/jpmml/model/XPathUtilTest.java index 22d07ed3..2edde8dd 100644 --- a/pmml-model/src/test/java/org/jpmml/model/XPathUtilTest.java +++ b/pmml-model/src/test/java/org/jpmml/model/XPathUtilTest.java @@ -3,13 +3,22 @@ */ package org.jpmml.model; +import org.dmg.pmml.ComplexScoreDistribution; import org.dmg.pmml.DataField; import org.dmg.pmml.IntSparseArray; import org.dmg.pmml.PMMLAttributes; import org.dmg.pmml.PMMLElements; +import org.dmg.pmml.ScoreDistribution; +import org.dmg.pmml.ScoreProbability; +import org.dmg.pmml.SimpleScoreDistribution; +import org.dmg.pmml.tree.ComplexNode; +import org.dmg.pmml.tree.LeafNode; +import org.dmg.pmml.tree.Node; +import org.dmg.pmml.tree.SimpleNode; import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; public class XPathUtilTest { @@ -41,11 +50,65 @@ public void formatDerivedField(){ assertEquals("DerivedField/", XPathUtil.formatElementOrAttribute(PMMLElements.DERIVEDFIELD_EXPRESSION)); } + @Test + public void formatComplexNode(){ + assertEquals("Node", XPathUtil.formatElement(ComplexNode.class)); + + assertEquals("Node@score", XPathUtil.formatElementOrAttribute(org.dmg.pmml.tree.PMMLAttributes.COMPLEXNODE_SCORE)); + assertEquals("Node/", XPathUtil.formatElementOrAttribute(org.dmg.pmml.tree.PMMLElements.COMPLEXNODE_PREDICATE)); + } + + @Test + public void formatSimpleNode(){ + SimpleNode node = new LeafNode(); + + Class nodeClazz = node.getClass(); + + assertEquals("Node", XPathUtil.formatElement(nodeClazz)); + + try { + XPathUtil.formatElementOrAttribute(ReflectionUtil.getField(nodeClazz, "score")); + + fail(); + } catch(IllegalArgumentException iae){ + // Ignored + } + + assertEquals("Node@score", XPathUtil.formatElementOrAttribute(nodeClazz, ReflectionUtil.getField(nodeClazz, "score"))); + assertEquals("Node/", XPathUtil.formatElementOrAttribute(nodeClazz, ReflectionUtil.getField(nodeClazz, "predicate"))); + } + @Test public void formatPMML(){ assertEquals("PMML/", XPathUtil.formatElementOrAttribute(PMMLElements.PMML_MODELS)); } + @Test + public void formatComplexScoreDistribution(){ + assertEquals("ScoreDistribution", XPathUtil.formatElement(ComplexScoreDistribution.class)); + + assertEquals("ScoreDistribution@value", XPathUtil.formatElementOrAttribute(PMMLAttributes.COMPLEXSCOREDISTRIBUTION_VALUE)); + } + + @Test + public void formatSimpleScoreDistribution(){ + SimpleScoreDistribution scoreDistribution = new ScoreProbability(); + + Class scoreDistributionClazz = scoreDistribution.getClass(); + + assertEquals("ScoreDistribution", XPathUtil.formatElement(scoreDistributionClazz)); + + try { + XPathUtil.formatElementOrAttribute(ReflectionUtil.getField(scoreDistributionClazz, "value")); + + fail(); + } catch(IllegalArgumentException iae){ + // Ignored + } + + assertEquals("ScoreDistribution@value", XPathUtil.formatElementOrAttribute(scoreDistributionClazz, ReflectionUtil.getField(scoreDistributionClazz, "value"))); + } + @Test public void formatSegment(){ assertEquals("Segment/", XPathUtil.formatElementOrAttribute(org.dmg.pmml.mining.PMMLElements.SEGMENT_MODEL)); From f19144d5529fcc0527c342930262da40a2d8a931 Mon Sep 17 00:00:00 2001 From: Villu Ruusmann Date: Thu, 14 Nov 2024 22:03:17 +0200 Subject: [PATCH 06/16] Added @Added#removable field --- .../src/main/java/org/jpmml/model/annotations/Added.java | 2 ++ .../main/java/org/jpmml/model/visitors/VersionInspector.java | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/pmml-model/src/main/java/org/jpmml/model/annotations/Added.java b/pmml-model/src/main/java/org/jpmml/model/annotations/Added.java index ad2b1281..d7f2ad69 100644 --- a/pmml-model/src/main/java/org/jpmml/model/annotations/Added.java +++ b/pmml-model/src/main/java/org/jpmml/model/annotations/Added.java @@ -24,4 +24,6 @@ public @interface Added { Version value(); + + boolean removable() default false; } \ No newline at end of file diff --git a/pmml-model/src/main/java/org/jpmml/model/visitors/VersionInspector.java b/pmml-model/src/main/java/org/jpmml/model/visitors/VersionInspector.java index 7a5fe652..03127340 100644 --- a/pmml-model/src/main/java/org/jpmml/model/visitors/VersionInspector.java +++ b/pmml-model/src/main/java/org/jpmml/model/visitors/VersionInspector.java @@ -97,6 +97,11 @@ public Class annotationType(){ public Version value(){ return version; } + + @Override + public boolean removable(){ + return false; + } }; handleAdded(apply, PMMLAttributes.APPLY_FUNCTION, added); From f402b0e537d4e40063a3a1a29806d8a78e7a99f6 Mon Sep 17 00:00:00 2001 From: Villu Ruusmann Date: Fri, 15 Nov 2024 20:12:21 +0200 Subject: [PATCH 07/16] Updated @Added annotation for XPMML markup --- pmml-model/src/main/schema/pmml.xjb | 40 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/pmml-model/src/main/schema/pmml.xjb b/pmml-model/src/main/schema/pmml.xjb index 151886dc..af2be6ac 100644 --- a/pmml-model/src/main/schema/pmml.xjb +++ b/pmml-model/src/main/schema/pmml.xjb @@ -91,7 +91,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.5.0") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.3") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.XPMML) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.XPMML, removable = true) org.jpmml.model.annotations.Since("1.3.7") Date: Fri, 15 Nov 2024 21:50:26 +0200 Subject: [PATCH 08/16] Imported Java code from the JPMML-Converter project --- .../model/visitors/VersionStandardizer.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 pmml-model/src/main/java/org/jpmml/model/visitors/VersionStandardizer.java diff --git a/pmml-model/src/main/java/org/jpmml/model/visitors/VersionStandardizer.java b/pmml-model/src/main/java/org/jpmml/model/visitors/VersionStandardizer.java new file mode 100644 index 00000000..71195adf --- /dev/null +++ b/pmml-model/src/main/java/org/jpmml/model/visitors/VersionStandardizer.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 Villu Ruusmann + */ +package org.jpmml.model.visitors; + +import org.dmg.pmml.MathContext; +import org.dmg.pmml.Model; +import org.dmg.pmml.PMML; +import org.dmg.pmml.VisitorAction; + +public class VersionStandardizer extends AbstractVisitor { + + @Override + public VisitorAction visit(Model model){ + MathContext mathContext = model.getMathContext(); + + if(mathContext != null){ + model.setMathContext(null); + } + + return super.visit(model); + } + + @Override + public VisitorAction visit(PMML pmml){ + String baseVersion = pmml.getBaseVersion(); + + if(baseVersion != null){ + pmml.setBaseVersion(null); + } + + return super.visit(pmml); + } +} \ No newline at end of file From fcba77ca85684d8fb8a2aa68e2c0954a2312214b Mon Sep 17 00:00:00 2001 From: Villu Ruusmann Date: Sat, 16 Nov 2024 07:24:43 +0200 Subject: [PATCH 09/16] Refactored VersionStandardizer visitor class --- .../model/visitors/VersionStandardizer.java | 60 +++++++++++++------ .../visitors/VersionStandardizerTest.java | 41 +++++++++++++ 2 files changed, 83 insertions(+), 18 deletions(-) create mode 100644 pmml-model/src/test/java/org/jpmml/model/visitors/VersionStandardizerTest.java diff --git a/pmml-model/src/main/java/org/jpmml/model/visitors/VersionStandardizer.java b/pmml-model/src/main/java/org/jpmml/model/visitors/VersionStandardizer.java index 71195adf..680a9277 100644 --- a/pmml-model/src/main/java/org/jpmml/model/visitors/VersionStandardizer.java +++ b/pmml-model/src/main/java/org/jpmml/model/visitors/VersionStandardizer.java @@ -3,32 +3,56 @@ */ package org.jpmml.model.visitors; -import org.dmg.pmml.MathContext; -import org.dmg.pmml.Model; -import org.dmg.pmml.PMML; -import org.dmg.pmml.VisitorAction; - -public class VersionStandardizer extends AbstractVisitor { +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Field; + +import org.dmg.pmml.PMMLObject; +import org.dmg.pmml.Version; +import org.jpmml.model.ReflectionUtil; +import org.jpmml.model.annotations.Added; +import org.jpmml.model.annotations.Optional; +import org.jpmml.model.annotations.Removed; +import org.jpmml.model.annotations.Required; +import org.jpmml.model.filters.ExportFilter; + +/** + *

+ * A Visitor that standardizes a class model object by reducing vendor extension markup. + *

+ * + * @see ExportFilter + */ +public class VersionStandardizer extends VersionInspector { @Override - public VisitorAction visit(Model model){ - MathContext mathContext = model.getMathContext(); + public void handleAdded(PMMLObject object, AnnotatedElement element, Added added){ + Version version = added.value(); - if(mathContext != null){ - model.setMathContext(null); - } + if(!version.isStandard()){ - return super.visit(model); + if(element instanceof Field){ + Field field = (Field)element; + + if(added.removable()){ + ReflectionUtil.setFieldValue(field, object, null); + } + } else + + { + throw new IllegalArgumentException(); + } + } } @Override - public VisitorAction visit(PMML pmml){ - String baseVersion = pmml.getBaseVersion(); + public void handleRemoved(PMMLObject object, AnnotatedElement element, Removed removed){ + } - if(baseVersion != null){ - pmml.setBaseVersion(null); - } + @Override + public void handleOptional(PMMLObject object, AnnotatedElement element, Optional optional){ + } - return super.visit(pmml); + @Override + public void handleRequired(PMMLObject object, AnnotatedElement element, Required required){ } } \ No newline at end of file diff --git a/pmml-model/src/test/java/org/jpmml/model/visitors/VersionStandardizerTest.java b/pmml-model/src/test/java/org/jpmml/model/visitors/VersionStandardizerTest.java new file mode 100644 index 00000000..204943ac --- /dev/null +++ b/pmml-model/src/test/java/org/jpmml/model/visitors/VersionStandardizerTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 Villu Ruusmann + */ +package org.jpmml.model.visitors; + +import org.dmg.pmml.MathContext; +import org.dmg.pmml.PMML; +import org.dmg.pmml.tree.PMMLAttributes; +import org.dmg.pmml.tree.TreeModel; +import org.jpmml.model.ReflectionUtil; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +public class VersionStandardizerTest { + + @Test + public void standardize(){ + PMML pmml = new PMML() + .setVersion("4.4") + .setBaseVersion("4.3"); + + TreeModel treeModel = new TreeModel() + .setMathContext(MathContext.FLOAT); + + pmml.addModels(treeModel); + + VersionStandardizer inspector = new VersionStandardizer(); + inspector.applyTo(pmml); + + assertNotNull(pmml.getVersion()); + assertNull(pmml.getBaseVersion()); + + // The getter method is returning the default field value + assertEquals(MathContext.DOUBLE, treeModel.getMathContext()); + + assertNull(ReflectionUtil.getFieldValue(PMMLAttributes.TREEMODEL_MATHCONTEXT, treeModel)); + } +} \ No newline at end of file From aea9d7b10e1cb492e9b0199712ab5460be414c16 Mon Sep 17 00:00:00 2001 From: Villu Ruusmann Date: Sat, 16 Nov 2024 22:51:45 +0200 Subject: [PATCH 10/16] Updated @Added annotation for standard markup --- pmml-model/src/main/schema/pmml.xjb | 114 ++++++++++++++-------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/pmml-model/src/main/schema/pmml.xjb b/pmml-model/src/main/schema/pmml.xjb index af2be6ac..ad33273e 100644 --- a/pmml-model/src/main/schema/pmml.xjb +++ b/pmml-model/src/main/schema/pmml.xjb @@ -194,7 +194,7 @@ Copyright (c) 2014 Villu Ruusmann
- org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_4) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_4, removable = true) @@ -234,7 +234,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -261,7 +261,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -341,7 +341,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -451,7 +451,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_4) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_4, removable = true) @@ -589,7 +589,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -622,7 +622,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_0) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_0, removable = true) @@ -631,7 +631,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_4) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_4, removable = true) @@ -872,7 +872,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_0) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_0, removable = true) @@ -1209,7 +1209,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -1311,7 +1311,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_0) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_0, removable = true) @@ -1323,7 +1323,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_3) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_3, removable = true) @@ -1589,7 +1589,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -1612,7 +1612,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_0) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_0, removable = true) @@ -1719,7 +1719,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -1734,7 +1734,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_0) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_0, removable = true) @@ -1760,7 +1760,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -1831,7 +1831,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -1868,7 +1868,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_0) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_0, removable = true) @@ -2060,7 +2060,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_3) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_3, removable = true) @@ -2159,7 +2159,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_4) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_4, removable = true) @@ -2193,7 +2193,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_4) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_4, removable = true) @@ -2363,27 +2363,27 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_4) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_4, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_4) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_4, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -2393,59 +2393,59 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_4) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_4, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_4) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_4, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_4) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_4, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_4) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_4, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_4) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_4, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_4) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_4, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -2536,7 +2536,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_0) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_0, removable = true) @@ -2557,7 +2557,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -2603,7 +2603,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_0) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_0, removable = true) @@ -2705,7 +2705,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -2720,7 +2720,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_0) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_0, removable = true) @@ -2739,7 +2739,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -2921,7 +2921,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -3151,7 +3151,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -3192,7 +3192,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_0) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_0, removable = true) @@ -3406,7 +3406,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -3421,7 +3421,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_0) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_0, removable = true) @@ -3593,7 +3593,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -3612,7 +3612,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -3671,7 +3671,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_1) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_1, removable = true) @@ -3722,7 +3722,7 @@ Copyright (c) 2014 Villu Ruusmann - org.jpmml.model.annotations.Added(org.dmg.pmml.Version.PMML_4_0) + org.jpmml.model.annotations.Added(value = org.dmg.pmml.Version.PMML_4_0, removable = true) From 6a10c25f65fca0ef47f95b36869bc57b29a3bb3d Mon Sep 17 00:00:00 2001 From: Villu Ruusmann Date: Sun, 17 Nov 2024 08:36:07 +0200 Subject: [PATCH 11/16] Added VersionDowngrader visitor class --- .../model/visitors/VersionDowngrader.java | 74 +++++++++++++++ .../model/visitors/VersionStandardizer.java | 4 + .../model/visitors/VersionDowngraderTest.java | 89 +++++++++++++++++++ 3 files changed, 167 insertions(+) create mode 100644 pmml-model/src/main/java/org/jpmml/model/visitors/VersionDowngrader.java create mode 100644 pmml-model/src/test/java/org/jpmml/model/visitors/VersionDowngraderTest.java diff --git a/pmml-model/src/main/java/org/jpmml/model/visitors/VersionDowngrader.java b/pmml-model/src/main/java/org/jpmml/model/visitors/VersionDowngrader.java new file mode 100644 index 00000000..a29dfdec --- /dev/null +++ b/pmml-model/src/main/java/org/jpmml/model/visitors/VersionDowngrader.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2024 Villu Ruusmann + */ +package org.jpmml.model.visitors; + +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Field; +import java.util.Objects; + +import org.dmg.pmml.PMMLObject; +import org.dmg.pmml.Version; +import org.jpmml.model.ReflectionUtil; +import org.jpmml.model.annotations.Added; +import org.jpmml.model.annotations.Optional; +import org.jpmml.model.annotations.Removed; +import org.jpmml.model.annotations.Required; +import org.jpmml.model.filters.ExportFilter; + +/** + *

+ * A Visitor that downgrades a class model object from the latest PMML schema version to some earlier one. + *

+ * + * @see ExportFilter + */ +public class VersionDowngrader extends VersionInspector { + + private Version version = null; + + + public VersionDowngrader(Version version){ + this.version = Objects.requireNonNull(version); + + if(!version.isStandard()){ + throw new IllegalArgumentException(); + } + } + + @Override + public void handleAdded(PMMLObject object, AnnotatedElement element, Added added){ + Version version = added.value(); + + if(version.isStandard() && version.compareTo(this.version) > 0){ + + if(element instanceof Class){ + // Ignored + } else + + if(element instanceof Field){ + Field field = (Field)element; + + if(added.removable()){ + ReflectionUtil.setFieldValue(field, object, null); + } + } else + + { + throw new IllegalArgumentException(); + } + } + } + + @Override + public void handleRemoved(PMMLObject object, AnnotatedElement element, Removed removed){ + } + + @Override + public void handleOptional(PMMLObject object, AnnotatedElement element, Optional optional){ + } + + @Override + public void handleRequired(PMMLObject object, AnnotatedElement element, Required required){ + } +} \ No newline at end of file diff --git a/pmml-model/src/main/java/org/jpmml/model/visitors/VersionStandardizer.java b/pmml-model/src/main/java/org/jpmml/model/visitors/VersionStandardizer.java index 680a9277..ee917373 100644 --- a/pmml-model/src/main/java/org/jpmml/model/visitors/VersionStandardizer.java +++ b/pmml-model/src/main/java/org/jpmml/model/visitors/VersionStandardizer.java @@ -30,6 +30,10 @@ public void handleAdded(PMMLObject object, AnnotatedElement element, Added added if(!version.isStandard()){ + if(element instanceof Class){ + // Ignored + } else + if(element instanceof Field){ Field field = (Field)element; diff --git a/pmml-model/src/test/java/org/jpmml/model/visitors/VersionDowngraderTest.java b/pmml-model/src/test/java/org/jpmml/model/visitors/VersionDowngraderTest.java new file mode 100644 index 00000000..e9d0baf7 --- /dev/null +++ b/pmml-model/src/test/java/org/jpmml/model/visitors/VersionDowngraderTest.java @@ -0,0 +1,89 @@ +/* + * Copyrght (c) 2024 Villu Ruusmann + */ +package org.jpmml.model.visitors; + +import org.dmg.pmml.ClusteringModelQuality; +import org.dmg.pmml.Extension; +import org.dmg.pmml.Header; +import org.dmg.pmml.ModelExplanation; +import org.dmg.pmml.PMML; +import org.dmg.pmml.Version; +import org.dmg.pmml.clustering.ClusteringModel; +import org.dmg.pmml.clustering.PMMLAttributes; +import org.jpmml.model.ReflectionUtil; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class VersionDowngraderTest { + + @Test + public void downgrade(){ + Extension extension = new Extension(); + + ClusteringModelQuality clusteringModelQuality = new ClusteringModelQuality() + .addExtensions(extension); + + ModelExplanation modelExplanation = new ModelExplanation() + .addClusteringModelQualities(clusteringModelQuality); + + ClusteringModel clusteringModel = new ClusteringModel() + .setScorable(false) + .setModelExplanation(modelExplanation); + + Header header = new Header() + .setModelVersion("1.0"); + + PMML pmml = new PMML() + .setHeader(header) + .addModels(clusteringModel); + + VersionInspector inspector; + + try { + inspector = new VersionDowngrader(Version.XPMML); + + fail(); + } catch(IllegalArgumentException iae){ + // Ignored + } + + inspector = new VersionDowngrader(Version.PMML_4_4); + inspector.applyTo(pmml); + + assertTrue(clusteringModelQuality.hasExtensions()); + + inspector = new VersionDowngrader(Version.PMML_4_3); + inspector.applyTo(pmml); + + assertFalse(clusteringModelQuality.hasExtensions()); + + assertNotNull(header.getModelVersion()); + + inspector = new VersionDowngrader(Version.PMML_4_1); + inspector.applyTo(pmml); + + assertNull(header.getModelVersion()); + + assertFalse(clusteringModel.isScorable()); + + inspector = new VersionDowngrader(Version.PMML_4_0); + inspector.applyTo(pmml); + + assertTrue(clusteringModel.isScorable()); + + assertNull(ReflectionUtil.getFieldValue(PMMLAttributes.CLUSTERINGMODEL_SCORABLE, clusteringModel)); + + assertNotNull(clusteringModel.getModelExplanation()); + + inspector = new VersionDowngrader(Version.PMML_3_2); + inspector.applyTo(pmml); + + assertNull(clusteringModel.getModelExplanation()); + } +} \ No newline at end of file From 36459a4b65e751e165c31d63fe1eb8546c7ba0e9 Mon Sep 17 00:00:00 2001 From: Villu Ruusmann Date: Mon, 18 Nov 2024 23:07:35 +0200 Subject: [PATCH 12/16] Added PMMLOutputStream class --- .../org/jpmml/model/PMMLOutputStream.java | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 pmml-model/src/main/java/org/jpmml/model/PMMLOutputStream.java diff --git a/pmml-model/src/main/java/org/jpmml/model/PMMLOutputStream.java b/pmml-model/src/main/java/org/jpmml/model/PMMLOutputStream.java new file mode 100644 index 00000000..79ec3250 --- /dev/null +++ b/pmml-model/src/main/java/org/jpmml/model/PMMLOutputStream.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2024 Villu Ruusmann + */ +package org.jpmml.model; + +import java.io.ByteArrayOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Objects; + +import org.dmg.pmml.Version; + +public class PMMLOutputStream extends FilterOutputStream { + + private Version version = null; + + private ByteArrayOutputStream buffer = new ByteArrayOutputStream(1024); + + + public PMMLOutputStream(OutputStream os, Version version){ + super(os); + + this.version = Objects.requireNonNull(version); + + if(!version.isStandard()){ + throw new IllegalArgumentException(); + } + } + + @Override + public void write(byte[] bytes) throws IOException { + this.write(bytes, 0, bytes.length); + } + + @Override + public void write(byte[] bytes, int offset, int length) throws IOException { + + if(this.buffer != null){ + + for(int i = offset, max = offset + length; i < max; i++){ + this.write(bytes[i]); + } + } else + + { + super.out.write(bytes, offset, length); + } + } + + @Override + public void write(int b) throws IOException { + + if(this.buffer != null){ + this.buffer.write(b); + + if(b == '>'){ + String string = this.buffer.toString("UTF-8"); + + if(string.endsWith("?>")){ + super.out.write(string.getBytes("UTF-8")); + + this.buffer.reset(); + } else + + if(string.endsWith(">")){ + String updatedString = string.replace(Version.PMML_4_4.getNamespaceURI(), this.version.getNamespaceURI()); + + if(Objects.equals(string, updatedString)){ + throw new IllegalStateException(); + } + + super.out.write(updatedString.getBytes("UTF-8")); + + this.buffer = null; + } else + + { + throw new IllegalStateException(); + } + } + } else + + { + super.out.write(b); + } + } + + @Override + public void flush() throws IOException { + + if(this.buffer != null){ + throw new IllegalStateException(); + } + + super.flush(); + } + + @Override + public void close() throws IOException { + super.close(); + } +} \ No newline at end of file From b1295d51308ffcf4be4dbe5e15c0cbed60ff4470 Mon Sep 17 00:00:00 2001 From: Villu Ruusmann Date: Tue, 19 Nov 2024 22:34:26 +0200 Subject: [PATCH 13/16] Added version downgrade transformations --- .../model/visitors/VersionDowngrader.java | 79 +++++++++++ .../model/visitors/VersionDowngraderTest.java | 127 +++++++++++++++--- .../visitors/VersionStandardizerTest.java | 2 +- 3 files changed, 186 insertions(+), 22 deletions(-) diff --git a/pmml-model/src/main/java/org/jpmml/model/visitors/VersionDowngrader.java b/pmml-model/src/main/java/org/jpmml/model/visitors/VersionDowngrader.java index a29dfdec..10aa74d1 100644 --- a/pmml-model/src/main/java/org/jpmml/model/visitors/VersionDowngrader.java +++ b/pmml-model/src/main/java/org/jpmml/model/visitors/VersionDowngrader.java @@ -7,9 +7,18 @@ import java.lang.reflect.Field; import java.util.Objects; +import org.dmg.pmml.Apply; +import org.dmg.pmml.MiningField; +import org.dmg.pmml.PMML; +import org.dmg.pmml.PMMLAttributes; import org.dmg.pmml.PMMLObject; +import org.dmg.pmml.TargetValue; import org.dmg.pmml.Version; +import org.dmg.pmml.VisitorAction; +import org.dmg.pmml.time_series.TrendExpoSmooth; import org.jpmml.model.ReflectionUtil; +import org.jpmml.model.UnsupportedAttributeException; +import org.jpmml.model.UnsupportedElementException; import org.jpmml.model.annotations.Added; import org.jpmml.model.annotations.Optional; import org.jpmml.model.annotations.Removed; @@ -71,4 +80,74 @@ public void handleOptional(PMMLObject object, AnnotatedElement element, Optional @Override public void handleRequired(PMMLObject object, AnnotatedElement element, Required required){ } + + @Override + public VisitorAction visit(Apply apply){ + Object defaultValue = apply.getDefaultValue(); + + if(defaultValue != null){ + + if(this.version.compareTo(Version.PMML_4_1) == 0){ + Object mapMissingTo = apply.getMapMissingTo(); + + if(mapMissingTo != null){ + throw new UnsupportedAttributeException(apply, PMMLAttributes.APPLY_DEFAULTVALUE, defaultValue); + } + + apply + .setDefaultValue(null) + .setMapMissingTo(defaultValue); + } + } + + return super.visit(apply); + } + + @Override + public VisitorAction visit(MiningField miningField){ + MiningField.UsageType usageType = miningField.getUsageType(); + + switch(usageType){ + case TARGET: + if(this.version.compareTo(Version.PMML_4_2) < 0){ + miningField.setUsageType(MiningField.UsageType.PREDICTED); + } + break; + default: + break; + } + + return super.visit(miningField); + } + + @Override + public VisitorAction visit(PMML pmml){ + pmml.setVersion(this.version.getVersion()); + + return super.visit(pmml); + } + + @Override + public VisitorAction visit(TargetValue targetValue){ + String displayValue = targetValue.getDisplayValue(); + + if(displayValue != null){ + + if(this.version.compareTo(Version.PMML_3_2) <= 0){ + throw new UnsupportedAttributeException(targetValue, PMMLAttributes.TARGETVALUE_DISPLAYVALUE, displayValue); + } + } + + return super.visit(targetValue); + } + + @Override + public VisitorAction visit(TrendExpoSmooth trendExpoSmooth){ + + if(this.version.compareTo(Version.PMML_4_0) == 0){ + throw new UnsupportedElementException(trendExpoSmooth); + } + + return super.visit(trendExpoSmooth); + } } \ No newline at end of file diff --git a/pmml-model/src/test/java/org/jpmml/model/visitors/VersionDowngraderTest.java b/pmml-model/src/test/java/org/jpmml/model/visitors/VersionDowngraderTest.java index e9d0baf7..e32623dc 100644 --- a/pmml-model/src/test/java/org/jpmml/model/visitors/VersionDowngraderTest.java +++ b/pmml-model/src/test/java/org/jpmml/model/visitors/VersionDowngraderTest.java @@ -3,17 +3,24 @@ */ package org.jpmml.model.visitors; +import org.dmg.pmml.Apply; import org.dmg.pmml.ClusteringModelQuality; import org.dmg.pmml.Extension; import org.dmg.pmml.Header; +import org.dmg.pmml.MiningField; import org.dmg.pmml.ModelExplanation; import org.dmg.pmml.PMML; +import org.dmg.pmml.PMMLObject; +import org.dmg.pmml.TargetValue; import org.dmg.pmml.Version; import org.dmg.pmml.clustering.ClusteringModel; import org.dmg.pmml.clustering.PMMLAttributes; +import org.dmg.pmml.time_series.TrendExpoSmooth; import org.jpmml.model.ReflectionUtil; +import org.jpmml.model.UnsupportedAttributeException; import org.junit.Test; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; @@ -23,7 +30,55 @@ public class VersionDowngraderTest { @Test - public void downgrade(){ + public void downgradeApply(){ + Apply apply = new Apply() + .setDefaultValue(0) + .setMapMissingTo(null); + + apply = downgrade(apply, Version.PMML_4_2); + + assertEquals(0, apply.getDefaultValue()); + assertNull(apply.getMapMissingTo()); + + apply = downgrade(apply, Version.PMML_4_1); + + assertNull(apply.getDefaultValue()); + assertEquals(0, apply.getMapMissingTo()); + + apply = new Apply() + .setDefaultValue(0) + .setMapMissingTo(-999); + + apply = downgrade(apply, Version.PMML_4_2); + + assertEquals(0, apply.getDefaultValue()); + assertEquals(-999, apply.getMapMissingTo()); + + try { + downgrade(apply, Version.PMML_4_1); + + fail(); + } catch(UnsupportedAttributeException uae){ + // Ignored + } + } + + @Test + public void downgradeMiningField(){ + MiningField miningField = new MiningField() + .setUsageType(MiningField.UsageType.TARGET); + + miningField = downgrade(miningField, Version.PMML_4_2); + + assertEquals(MiningField.UsageType.TARGET, miningField.getUsageType()); + + miningField = downgrade(miningField, Version.PMML_4_1); + + assertEquals(MiningField.UsageType.PREDICTED, miningField.getUsageType()); + } + + @Test + public void downgradePMML(){ Extension extension = new Extension(); ClusteringModelQuality clusteringModelQuality = new ClusteringModelQuality() @@ -43,37 +98,25 @@ public void downgrade(){ .setHeader(header) .addModels(clusteringModel); - VersionInspector inspector; - - try { - inspector = new VersionDowngrader(Version.XPMML); - - fail(); - } catch(IllegalArgumentException iae){ - // Ignored - } - - inspector = new VersionDowngrader(Version.PMML_4_4); - inspector.applyTo(pmml); + pmml = downgrade(pmml, Version.PMML_4_4); assertTrue(clusteringModelQuality.hasExtensions()); - inspector = new VersionDowngrader(Version.PMML_4_3); - inspector.applyTo(pmml); + assertEquals("4.4", pmml.getVersion()); + + pmml = downgrade(pmml, Version.PMML_4_3); assertFalse(clusteringModelQuality.hasExtensions()); assertNotNull(header.getModelVersion()); - inspector = new VersionDowngrader(Version.PMML_4_1); - inspector.applyTo(pmml); + pmml = downgrade(pmml, Version.PMML_4_1); assertNull(header.getModelVersion()); assertFalse(clusteringModel.isScorable()); - inspector = new VersionDowngrader(Version.PMML_4_0); - inspector.applyTo(pmml); + pmml = downgrade(pmml, Version.PMML_4_0); assertTrue(clusteringModel.isScorable()); @@ -81,9 +124,51 @@ public void downgrade(){ assertNotNull(clusteringModel.getModelExplanation()); - inspector = new VersionDowngrader(Version.PMML_3_2); - inspector.applyTo(pmml); + pmml = downgrade(pmml, Version.PMML_3_2); assertNull(clusteringModel.getModelExplanation()); + + assertEquals("3.2", pmml.getVersion()); + } + + @Test + public void downgradeTargetValue(){ + TargetValue targetValue = new TargetValue() + .setValue(1) + .setDisplayValue("one"); + + targetValue = downgrade(targetValue, Version.PMML_4_0); + + assertEquals(1, targetValue.getValue()); + assertEquals("one", targetValue.getDisplayValue()); + + try { + downgrade(targetValue, Version.PMML_3_2); + + fail(); + } catch(UnsupportedAttributeException uae){ + // Ignored + } + } + + @Test + public void downgradeTrendExpoSmooth(){ + TrendExpoSmooth trendExpoSmooth = new TrendExpoSmooth(); + + trendExpoSmooth = downgrade(trendExpoSmooth, Version.PMML_4_1); + + try { + downgrade(trendExpoSmooth, Version.PMML_4_0); + } catch(IllegalArgumentException iae){ + // Ignored + } + } + + static + private E downgrade(E object, Version version){ + VersionDowngrader inspector = new VersionDowngrader(version); + inspector.applyTo(object); + + return object; } } \ No newline at end of file diff --git a/pmml-model/src/test/java/org/jpmml/model/visitors/VersionStandardizerTest.java b/pmml-model/src/test/java/org/jpmml/model/visitors/VersionStandardizerTest.java index 204943ac..103070f3 100644 --- a/pmml-model/src/test/java/org/jpmml/model/visitors/VersionStandardizerTest.java +++ b/pmml-model/src/test/java/org/jpmml/model/visitors/VersionStandardizerTest.java @@ -17,7 +17,7 @@ public class VersionStandardizerTest { @Test - public void standardize(){ + public void standardizePMML(){ PMML pmml = new PMML() .setVersion("4.4") .setBaseVersion("4.3"); From 8777fb01e8278e07ac92d672335ba551d2dea19b Mon Sep 17 00:00:00 2001 From: Villu Ruusmann Date: Wed, 20 Nov 2024 09:54:47 +0200 Subject: [PATCH 14/16] Improved class model generation All PMMLObject subclasses are expected to have type-level @XmlRootElement and @JsonRootName annotations. --- .../model/visitors/VersionDowngraderTest.java | 3 +- .../java/org/jpmml/xjc/CodeModelUtil.java | 94 ++++++++++++ .../java/org/jpmml/xjc/JacksonPlugin.java | 14 +- .../main/java/org/jpmml/xjc/PMMLPlugin.java | 142 ++++++++---------- 4 files changed, 172 insertions(+), 81 deletions(-) diff --git a/pmml-model/src/test/java/org/jpmml/model/visitors/VersionDowngraderTest.java b/pmml-model/src/test/java/org/jpmml/model/visitors/VersionDowngraderTest.java index e32623dc..229a0032 100644 --- a/pmml-model/src/test/java/org/jpmml/model/visitors/VersionDowngraderTest.java +++ b/pmml-model/src/test/java/org/jpmml/model/visitors/VersionDowngraderTest.java @@ -18,6 +18,7 @@ import org.dmg.pmml.time_series.TrendExpoSmooth; import org.jpmml.model.ReflectionUtil; import org.jpmml.model.UnsupportedAttributeException; +import org.jpmml.model.UnsupportedElementException; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -159,7 +160,7 @@ public void downgradeTrendExpoSmooth(){ try { downgrade(trendExpoSmooth, Version.PMML_4_0); - } catch(IllegalArgumentException iae){ + } catch(UnsupportedElementException uee){ // Ignored } } diff --git a/pmml-xjc/src/main/java/org/jpmml/xjc/CodeModelUtil.java b/pmml-xjc/src/main/java/org/jpmml/xjc/CodeModelUtil.java index acda944e..2c53cf8e 100644 --- a/pmml-xjc/src/main/java/org/jpmml/xjc/CodeModelUtil.java +++ b/pmml-xjc/src/main/java/org/jpmml/xjc/CodeModelUtil.java @@ -3,9 +3,18 @@ */ package org.jpmml.xjc; +import java.io.IOException; +import java.io.StringWriter; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.util.Collection; import java.util.List; +import com.sun.codemodel.JAnnotatable; +import com.sun.codemodel.JAnnotationUse; import com.sun.codemodel.JClass; +import com.sun.codemodel.JFormatter; +import com.sun.codemodel.JGenerable; import com.sun.codemodel.JType; public class CodeModelUtil { @@ -24,4 +33,89 @@ public JType getElementType(JType collectionType){ return elementTypes.get(0); } + + static + public boolean hasAnnotation(Collection annotations, Class clazz){ + JAnnotationUse annotation = findAnnotation(annotations, clazz); + + return (annotation != null); + } + + static + public JAnnotationUse findAnnotation(Collection annotations, Class clazz){ + String fullName = clazz.getName(); + + for(JAnnotationUse annotation : annotations){ + JClass type = annotation.getAnnotationClass(); + + if((type.fullName()).equals(fullName)){ + return annotation; + } + } + + return null; + } + + static + public List getAnnotations(JAnnotatable annotatable){ + + try { + Class clazz = annotatable.getClass(); + + Field annotationsField; + + while(true){ + + try { + annotationsField = clazz.getDeclaredField("annotations"); + + break; + } catch(NoSuchFieldException nsfe){ + clazz = clazz.getSuperclass(); + + if(clazz == null){ + throw nsfe; + } + } + } + + ensureAccessible(annotationsField); + + return (List)annotationsField.get(annotatable); + } catch(ReflectiveOperationException roe){ + throw new RuntimeException(roe); + } + } + + static + public String stringValue(JGenerable generable){ + String result; + + try(StringWriter writer = new StringWriter()){ + generable.generate(new JFormatter(writer)); + + result = writer.toString(); + } catch(IOException ioe){ + throw new RuntimeException(ioe); + } + + if(result.length() >= 2 && (result.startsWith("\"") && result.endsWith("\""))){ + result = result.substring(1, result.length() - 1); + } else + + { + throw new RuntimeException(); + } + + return result; + } + + @SuppressWarnings("deprecation") + static + void ensureAccessible(AccessibleObject accessibleObject){ + + if(!accessibleObject.isAccessible()){ + accessibleObject.setAccessible(true); + } + } } \ No newline at end of file diff --git a/pmml-xjc/src/main/java/org/jpmml/xjc/JacksonPlugin.java b/pmml-xjc/src/main/java/org/jpmml/xjc/JacksonPlugin.java index c2d3c74f..3ef285d8 100644 --- a/pmml-xjc/src/main/java/org/jpmml/xjc/JacksonPlugin.java +++ b/pmml-xjc/src/main/java/org/jpmml/xjc/JacksonPlugin.java @@ -17,6 +17,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.sun.codemodel.JAnnotationArrayMember; import com.sun.codemodel.JAnnotationUse; +import com.sun.codemodel.JAnnotationValue; import com.sun.codemodel.JClass; import com.sun.codemodel.JCodeModel; import com.sun.codemodel.JDefinedClass; @@ -38,6 +39,7 @@ import com.sun.tools.xjc.outline.EnumOutline; import com.sun.tools.xjc.outline.FieldOutline; import com.sun.tools.xjc.outline.Outline; +import jakarta.xml.bind.annotation.XmlRootElement; import org.xml.sax.ErrorHandler; public class JacksonPlugin extends Plugin { @@ -58,14 +60,18 @@ public boolean run(Outline outline, Options options, ErrorHandler errorHandler){ Collection classOutlines = outline.getClasses(); for(ClassOutline classOutline : classOutlines){ - CClassInfo classInfo = classOutline.target; JDefinedClass beanClazz = classOutline.implClass; - if(classInfo.isElement()){ - QName elementName = classInfo.getElementName(); + List beanClazzAnnotations = CodeModelUtil.getAnnotations(beanClazz); + + JAnnotationUse xmlRootElement = CodeModelUtil.findAnnotation(beanClazzAnnotations, XmlRootElement.class); + if(xmlRootElement != null){ + Map annotationMembers = xmlRootElement.getAnnotationMembers(); + + JAnnotationValue nameValue = annotationMembers.get("name"); JAnnotationUse jsonRootName = beanClazz.annotate(JsonRootName.class) - .param("value", elementName.getLocalPart()); + .param("value", CodeModelUtil.stringValue(nameValue)); } FieldOutline[] fieldOutlines = classOutline.getDeclaredFields(); diff --git a/pmml-xjc/src/main/java/org/jpmml/xjc/PMMLPlugin.java b/pmml-xjc/src/main/java/org/jpmml/xjc/PMMLPlugin.java index 141ca4e8..a2efbbfb 100644 --- a/pmml-xjc/src/main/java/org/jpmml/xjc/PMMLPlugin.java +++ b/pmml-xjc/src/main/java/org/jpmml/xjc/PMMLPlugin.java @@ -4,7 +4,6 @@ */ package org.jpmml.xjc; -import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; @@ -20,7 +19,6 @@ import javax.xml.namespace.QName; -import com.sun.codemodel.JAnnotatable; import com.sun.codemodel.JAnnotationArrayMember; import com.sun.codemodel.JAnnotationUse; import com.sun.codemodel.JAnnotationValue; @@ -59,6 +57,7 @@ import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlElements; import jakarta.xml.bind.annotation.XmlRootElement; +import jakarta.xml.bind.annotation.XmlType; import jakarta.xml.bind.annotation.XmlValue; import org.eclipse.persistence.oxm.annotations.XmlValueExtension; import org.glassfish.jaxb.core.api.impl.NameConverter; @@ -151,7 +150,7 @@ public int compare(CPropertyInfo left, CPropertyInfo right){ try { Field pkgField = CClassInfoParent.Package.class.getDeclaredField("pkg"); - ensureAccessible(pkgField); + CodeModelUtil.ensureAccessible(pkgField); JPackage subPackage = packageParent.pkg.subPackage(name); @@ -166,7 +165,7 @@ public int compare(CPropertyInfo left, CPropertyInfo right){ try { Field elementNameField = CClassInfo.class.getDeclaredField("elementName"); - ensureAccessible(elementNameField); + CodeModelUtil.ensureAccessible(elementNameField); elementNameField.set(classInfo, new QName("http://www.dmg.org/PMML-4_4", name)); } catch(ReflectiveOperationException roe){ @@ -312,17 +311,40 @@ public boolean run(Outline outline, Options options, ErrorHandler errorHandler){ for(ClassOutline classOutline : classOutlines){ JDefinedClass beanClazz = classOutline.implClass; - List beanClazzAnnotations = getAnnotations(beanClazz); + List beanClazzAnnotations = CodeModelUtil.getAnnotations(beanClazz); - JAnnotationUse xmlAccessorType = findAnnotation(beanClazzAnnotations, XmlAccessorType.class); + JAnnotationUse xmlAccessorType = CodeModelUtil.findAnnotation(beanClazzAnnotations, XmlAccessorType.class); if(xmlAccessorType != null){ beanClazzAnnotations.remove(xmlAccessorType); } - JAnnotationUse xmlRootElement = findAnnotation(beanClazzAnnotations, XmlRootElement.class); + JAnnotationUse xmlType = CodeModelUtil.findAnnotation(beanClazzAnnotations, XmlType.class); + if(xmlType != null){ + beanClazzAnnotations.remove(xmlType); + beanClazzAnnotations.add(0, xmlType); + } else + + { + throw new RuntimeException(); + } + + JAnnotationUse xmlRootElement = CodeModelUtil.findAnnotation(beanClazzAnnotations, XmlRootElement.class); + if(xmlRootElement == null){ + String elementName = getElementName(beanClazz.name()); + + beanClazz.annotate(XmlRootElement.class) + .param("name", elementName) + .param("namespace", "http://www.dmg.org/PMML-4_4"); + } + + xmlRootElement = CodeModelUtil.findAnnotation(beanClazzAnnotations, XmlRootElement.class); if(xmlRootElement != null){ beanClazzAnnotations.remove(xmlRootElement); beanClazzAnnotations.add(0, xmlRootElement); + } else + + { + throw new RuntimeException(); } Map fieldVars = beanClazz.fields(); @@ -457,11 +479,11 @@ public boolean run(Outline outline, Options options, ErrorHandler errorHandler){ } } - List fieldVarAnnotations = getAnnotations(fieldVar); + List fieldVarAnnotations = CodeModelUtil.getAnnotations(fieldVar); // XXX if(("node").equals(name) || ("nodes").equals(name) || ("scoreDistributions").equals(name)){ - JAnnotationUse xmlElement = findAnnotation(fieldVarAnnotations, XmlElement.class); + JAnnotationUse xmlElement = CodeModelUtil.findAnnotation(fieldVarAnnotations, XmlElement.class); fieldVarAnnotations.remove(xmlElement); @@ -477,7 +499,7 @@ public boolean run(Outline outline, Options options, ErrorHandler errorHandler){ fieldVarAnnotations.add(0, xmlElements); } // End if - if(hasAnnotation(fieldVarAnnotations, XmlValue.class)){ + if(CodeModelUtil.hasAnnotation(fieldVarAnnotations, XmlValue.class)){ fieldVar.annotate(XmlValueExtension.class); } } @@ -639,6 +661,36 @@ public boolean run(Outline outline, Options options, ErrorHandler errorHandler){ return true; } + static + private String getElementName(String name){ + + switch(name){ + // baseline + case "CountTable": + return "COUNT-TABLE-TYPE"; + // bayesian_network + case "ContinuousDistribution": + return name; + // bayesian_network + case "LognormalDistribution": + case "NormalDistribution": + case "TriangularDistribution": + case "UniformDistribution": + return name + "ForBN"; + // support_vector_machne + case "LinearKernel": + case "PolynomialKernel": + case "RadialBasisKernel": + case "SigmoidKernel": + return name + "Type"; + // time_series + case "TrendExpoSmooth": + return "Trend_ExpoSmooth"; + default: + throw new IllegalArgumentException(name); + } + } + static private FieldOutline getExtensionsField(ClassOutline classOutline){ Predicate predicate = new Predicate(){ @@ -690,65 +742,12 @@ public boolean test(FieldOutline fieldOutline){ .findFirst().orElse(null); } - static - private boolean hasAnnotation(Collection annotations, Class clazz){ - JAnnotationUse annotation = findAnnotation(annotations, clazz); - - return (annotation != null); - } - - static - private JAnnotationUse findAnnotation(Collection annotations, Class clazz){ - String fullName = clazz.getName(); - - for(JAnnotationUse annotation : annotations){ - JClass type = annotation.getAnnotationClass(); - - if(checkType(type, fullName)){ - return annotation; - } - } - - return null; - } - - static - private List getAnnotations(JAnnotatable annotatable){ - - try { - Class clazz = annotatable.getClass(); - - Field annotationsField; - - while(true){ - - try { - annotationsField = clazz.getDeclaredField("annotations"); - - break; - } catch(NoSuchFieldException nsfe){ - clazz = clazz.getSuperclass(); - - if(clazz == null){ - throw nsfe; - } - } - } - - ensureAccessible(annotationsField); - - return (List)annotationsField.get(annotatable); - } catch(ReflectiveOperationException roe){ - throw new RuntimeException(roe); - } - } - static private void addValues(JAnnotationUse annotationUse, Map memberValues){ try { Method addValueMethod = JAnnotationUse.class.getDeclaredMethod("addValue", String.class, JAnnotationValue.class); - ensureAccessible(addValueMethod); + CodeModelUtil.ensureAccessible(addValueMethod); Collection> entries = memberValues.entrySet(); for(Map.Entry entry : entries){ @@ -831,7 +830,7 @@ private JExpression constantExpr(JFieldVar fieldVar){ try { Field ownerField = JFieldVar.class.getDeclaredField("owner"); - ensureAccessible(ownerField); + CodeModelUtil.ensureAccessible(ownerField); owner = (JDefinedClass)ownerField.get(fieldVar); } catch(ReflectiveOperationException roe){ @@ -881,7 +880,7 @@ private void addOverrideAnnotations(JDefinedClass beanClazz, String[][] typeMemb if((name.startsWith("has") || name.startsWith("is") || name.startsWith("get") || name.startsWith("require")) && params.size() == 0){ - if(!hasAnnotation(method.annotations(), Override.class)){ + if(!CodeModelUtil.hasAnnotation(method.annotations(), Override.class)){ method.annotate(Override.class); } } else @@ -892,7 +891,7 @@ private void addOverrideAnnotations(JDefinedClass beanClazz, String[][] typeMemb if(name.startsWith("set") && params.size() == 1){ - if(!hasAnnotation(method.annotations(), Override.class)){ + if(!CodeModelUtil.hasAnnotation(method.annotations(), Override.class)){ method.annotate(Override.class); } } else @@ -944,15 +943,6 @@ private boolean checkType(JType type, String fullName){ return (type.fullName()).equals(fullName); } - @SuppressWarnings("deprecation") - static - private void ensureAccessible(AccessibleObject accessibleObject){ - - if(!accessibleObject.isAccessible()){ - accessibleObject.setAccessible(true); - } - } - static private int parseVersion(String version){ From cb5c51186602705fb38f3a80ff332b7e2a6ea3f9 Mon Sep 17 00:00:00 2001 From: Villu Ruusmann Date: Wed, 20 Nov 2024 10:05:26 +0200 Subject: [PATCH 15/16] [maven-release-plugin] prepare release 1.6.7 --- pmml-agent/pom.xml | 2 +- pmml-model-example/pom.xml | 2 +- pmml-model-gwt/pom.xml | 2 +- pmml-model-jackson/pom.xml | 2 +- pmml-model-kryo/pom.xml | 2 +- pmml-model-metro/pom.xml | 2 +- pmml-model-moxy/pom.xml | 2 +- pmml-model/pom.xml | 2 +- pmml-xjc/pom.xml | 2 +- pom.xml | 26 +++++++++++++------------- 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/pmml-agent/pom.xml b/pmml-agent/pom.xml index 47a26b9a..7ef42593 100644 --- a/pmml-agent/pom.xml +++ b/pmml-agent/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6-SNAPSHOT + 1.6.7 org.jpmml diff --git a/pmml-model-example/pom.xml b/pmml-model-example/pom.xml index a5f0a20d..9bb52e06 100644 --- a/pmml-model-example/pom.xml +++ b/pmml-model-example/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6-SNAPSHOT + 1.6.7 org.jpmml diff --git a/pmml-model-gwt/pom.xml b/pmml-model-gwt/pom.xml index eb2fd707..98199a48 100644 --- a/pmml-model-gwt/pom.xml +++ b/pmml-model-gwt/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6-SNAPSHOT + 1.6.7 org.jpmml diff --git a/pmml-model-jackson/pom.xml b/pmml-model-jackson/pom.xml index d6288c51..12ed4e78 100644 --- a/pmml-model-jackson/pom.xml +++ b/pmml-model-jackson/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6-SNAPSHOT + 1.6.7 org.jpmml diff --git a/pmml-model-kryo/pom.xml b/pmml-model-kryo/pom.xml index e1594b55..8ab0ed3f 100644 --- a/pmml-model-kryo/pom.xml +++ b/pmml-model-kryo/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6-SNAPSHOT + 1.6.7 org.jpmml diff --git a/pmml-model-metro/pom.xml b/pmml-model-metro/pom.xml index 60056beb..acfa5bf0 100644 --- a/pmml-model-metro/pom.xml +++ b/pmml-model-metro/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6-SNAPSHOT + 1.6.7 org.jpmml diff --git a/pmml-model-moxy/pom.xml b/pmml-model-moxy/pom.xml index 7ab39d9a..31944e7e 100644 --- a/pmml-model-moxy/pom.xml +++ b/pmml-model-moxy/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6-SNAPSHOT + 1.6.7 org.jpmml diff --git a/pmml-model/pom.xml b/pmml-model/pom.xml index dc34c9c7..8fb3137e 100644 --- a/pmml-model/pom.xml +++ b/pmml-model/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6-SNAPSHOT + 1.6.7 org.jpmml diff --git a/pmml-xjc/pom.xml b/pmml-xjc/pom.xml index ddbaad8f..1ce422fa 100644 --- a/pmml-xjc/pom.xml +++ b/pmml-xjc/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6-SNAPSHOT + 1.6.7 org.jpmml diff --git a/pom.xml b/pom.xml index c178b2bc..e7809434 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.jpmml jpmml-model - 1.6-SNAPSHOT + 1.6.7 pom JPMML-Model @@ -48,7 +48,7 @@ scm:git:git@github.com:jpmml/jpmml-model.git scm:git:git@github.com:jpmml/jpmml-model.git git://github.com/jpmml/jpmml-model.git - HEAD + 1.6.7 GitHub @@ -56,7 +56,7 @@ - 2024-10-01T16:19:34Z + 2024-11-20T08:01:46Z @@ -64,53 +64,53 @@ org.jpmml pmml-agent - 1.6-SNAPSHOT + 1.6.7 org.jpmml pmml-model - 1.6-SNAPSHOT + 1.6.7 org.jpmml pmml-model tests - 1.6-SNAPSHOT + 1.6.7 org.jpmml pmml-model-example - 1.6-SNAPSHOT + 1.6.7 org.jpmml pmml-model-gwt - 1.6-SNAPSHOT + 1.6.7 org.jpmml pmml-model-jackson - 1.6-SNAPSHOT + 1.6.7 org.jpmml pmml-model-kryo - 1.6-SNAPSHOT + 1.6.7 org.jpmml pmml-model-metro - 1.6-SNAPSHOT + 1.6.7 org.jpmml pmml-model-moxy - 1.6-SNAPSHOT + 1.6.7 org.jpmml pmml-xjc - 1.6-SNAPSHOT + 1.6.7 From b51ac0ee5320eeaf4486b394dedda73ccb5c15a4 Mon Sep 17 00:00:00 2001 From: Villu Ruusmann Date: Wed, 20 Nov 2024 10:05:26 +0200 Subject: [PATCH 16/16] [maven-release-plugin] prepare for next development iteration --- pmml-agent/pom.xml | 2 +- pmml-model-example/pom.xml | 2 +- pmml-model-gwt/pom.xml | 2 +- pmml-model-jackson/pom.xml | 2 +- pmml-model-kryo/pom.xml | 2 +- pmml-model-metro/pom.xml | 2 +- pmml-model-moxy/pom.xml | 2 +- pmml-model/pom.xml | 2 +- pmml-xjc/pom.xml | 2 +- pom.xml | 26 +++++++++++++------------- 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/pmml-agent/pom.xml b/pmml-agent/pom.xml index 7ef42593..47a26b9a 100644 --- a/pmml-agent/pom.xml +++ b/pmml-agent/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6.7 + 1.6-SNAPSHOT org.jpmml diff --git a/pmml-model-example/pom.xml b/pmml-model-example/pom.xml index 9bb52e06..a5f0a20d 100644 --- a/pmml-model-example/pom.xml +++ b/pmml-model-example/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6.7 + 1.6-SNAPSHOT org.jpmml diff --git a/pmml-model-gwt/pom.xml b/pmml-model-gwt/pom.xml index 98199a48..eb2fd707 100644 --- a/pmml-model-gwt/pom.xml +++ b/pmml-model-gwt/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6.7 + 1.6-SNAPSHOT org.jpmml diff --git a/pmml-model-jackson/pom.xml b/pmml-model-jackson/pom.xml index 12ed4e78..d6288c51 100644 --- a/pmml-model-jackson/pom.xml +++ b/pmml-model-jackson/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6.7 + 1.6-SNAPSHOT org.jpmml diff --git a/pmml-model-kryo/pom.xml b/pmml-model-kryo/pom.xml index 8ab0ed3f..e1594b55 100644 --- a/pmml-model-kryo/pom.xml +++ b/pmml-model-kryo/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6.7 + 1.6-SNAPSHOT org.jpmml diff --git a/pmml-model-metro/pom.xml b/pmml-model-metro/pom.xml index acfa5bf0..60056beb 100644 --- a/pmml-model-metro/pom.xml +++ b/pmml-model-metro/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6.7 + 1.6-SNAPSHOT org.jpmml diff --git a/pmml-model-moxy/pom.xml b/pmml-model-moxy/pom.xml index 31944e7e..7ab39d9a 100644 --- a/pmml-model-moxy/pom.xml +++ b/pmml-model-moxy/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6.7 + 1.6-SNAPSHOT org.jpmml diff --git a/pmml-model/pom.xml b/pmml-model/pom.xml index 8fb3137e..dc34c9c7 100644 --- a/pmml-model/pom.xml +++ b/pmml-model/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6.7 + 1.6-SNAPSHOT org.jpmml diff --git a/pmml-xjc/pom.xml b/pmml-xjc/pom.xml index 1ce422fa..ddbaad8f 100644 --- a/pmml-xjc/pom.xml +++ b/pmml-xjc/pom.xml @@ -5,7 +5,7 @@ org.jpmml jpmml-model - 1.6.7 + 1.6-SNAPSHOT org.jpmml diff --git a/pom.xml b/pom.xml index e7809434..75b0a25a 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.jpmml jpmml-model - 1.6.7 + 1.6-SNAPSHOT pom JPMML-Model @@ -48,7 +48,7 @@ scm:git:git@github.com:jpmml/jpmml-model.git scm:git:git@github.com:jpmml/jpmml-model.git git://github.com/jpmml/jpmml-model.git - 1.6.7 + HEAD GitHub @@ -56,7 +56,7 @@ - 2024-11-20T08:01:46Z + 2024-11-20T08:05:26Z @@ -64,53 +64,53 @@ org.jpmml pmml-agent - 1.6.7 + 1.6-SNAPSHOT org.jpmml pmml-model - 1.6.7 + 1.6-SNAPSHOT org.jpmml pmml-model tests - 1.6.7 + 1.6-SNAPSHOT org.jpmml pmml-model-example - 1.6.7 + 1.6-SNAPSHOT org.jpmml pmml-model-gwt - 1.6.7 + 1.6-SNAPSHOT org.jpmml pmml-model-jackson - 1.6.7 + 1.6-SNAPSHOT org.jpmml pmml-model-kryo - 1.6.7 + 1.6-SNAPSHOT org.jpmml pmml-model-metro - 1.6.7 + 1.6-SNAPSHOT org.jpmml pmml-model-moxy - 1.6.7 + 1.6-SNAPSHOT org.jpmml pmml-xjc - 1.6.7 + 1.6-SNAPSHOT