Closed janvanrijn closed 6 years ago
In order to complete the MWE here is also the DataQualities class (although it seems a bit unwieldy and unnecessary ):
import java.util.HashMap;
import java.util.Map;
import org.openml.apiconnector.settings.Constants;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
@XStreamAlias("oml:data_qualities")
public class DataQuality {
@XStreamAsAttribute
@XStreamAlias("xmlns:oml")
private final String oml = Constants.OPENML_XMLNS;
@XStreamAlias("xmlns:did")
private Integer did;
@XStreamAlias("oml:evaluation_engine_id")
private Integer evaluation_engine_id;
@XStreamAlias("oml:error")
private String error;
@XStreamImplicit
@XStreamAlias("oml:quality")
private Quality[] qualities;
public DataQuality(Integer did, Integer evaluation_engine_id, Quality[] qualities) {
this.did = did;
this.evaluation_engine_id = evaluation_engine_id;
this.qualities = qualities;
}
public DataQuality(Integer did, Integer evaluation_engine_id, String error) {
this.did = did;
this.evaluation_engine_id = evaluation_engine_id;
this.error = error;
}
public Integer getDid() {
return did;
}
public Integer getEvaluation_engine_id() {
return evaluation_engine_id;
}
public String getError() {
return error;
}
public Quality[] getQualities() {
return qualities;
}
public String[] getQualityNames() {
String[] result = new String[qualities.length];
for (int i = 0; i < qualities.length; ++i) {
result[i] = qualities[i].getName();
}
return result;
}
public Map<String,Double> getQualitiesMap() {
Map<String,Double> qm = new HashMap<String, Double>();
for (Quality q : qualities) {
qm.put(q.getName(), q.getValue());
}
return qm;
}
public String getOml() {
return oml;
}
@Override
public boolean equals(Object o) {
if(o != null) {
if(o instanceof DataQuality) {
DataQuality qualities = (DataQuality) o;
if(this.getQualitiesMap().equals(qualities.getQualitiesMap())) {
return true;
} else {
return false;
}
} else {
return false;
}
} else {
return false;
}
}
@Override
public int hashCode() {
return 11 * this.getQualitiesMap().hashCode();
}
@XStreamAlias("oml:quality")
public static class Quality {
@XStreamAlias("oml:name")
private String name;
@XStreamAlias("oml:feature_index")
private Integer feature_index;
@XStreamAlias("oml:value")
private Double value;
@XStreamAsAttribute
@XStreamAlias("oml:interval_start")
private Integer interval_start;
@XStreamAsAttribute
@XStreamAlias("oml:interval_end")
private Integer interval_end;
public Quality(String name, Double value) {
this.name = name;
this.value = value;
this.feature_index = null;
}
public Quality(String name, Double value, Integer intervat_start, Integer interval_end, Integer index) {
this.name = name;
this.value = value;
this.interval_start = intervat_start;
this.interval_end = interval_end;
this.feature_index = index;
}
public String getName() {
return name;
}
public Double getValue() {
return value;
}
public Integer getInterval_start() {
return interval_start;
}
public Integer getInterval_end() {
return interval_end;
}
public Integer getFeature_index() {
return feature_index;
}
@Override
public String toString() {
return name + ":" + value;
}
}
}
DoubleConverter is a SingleValueConverter, yet you did not override fromString. It simply has no unmarshal method, so it is no wonder that the method is never called if you implement one.
I really need to learn how to read, thanks a lot!
For the sake of competency, what would be the easiest way to make the toString method print a self-closing tag? I read this article but it doens't seem to cover it.
This is nothing that can be triggered in the converter of the object itself. A converter is always only responsible for the object's value, never for the surrounding tag. Only if an object consists of multiple values, the converter may create tags for its children and then let XStream select the appropriate converters and write the children's values again.
And it depends solely on the implementation of the XML writer. Most drivers will use XStream's own PrettyPrintWriter though and that one will create an empty tag if startElement and endElement is called without any setValue call in between. However, XStream's converters will typically generate no tag at all for null values.
I have the following XML (simplified):
Because of the self-closing tags, I created the following subclass of DoubleConverter:
And register it accordingly:
When adding a debug message in EmptyDoubleConverter it indicates that it can convert, but it never reaches the unmarshal function.