Hi all,
Maybe this is a topic more related to EMF serialization but as I'm working in a Xtext project, I'm asking here.
I have a grammar with a rule containing an optional element (port_value) of type int:
Node:
'__Node' name=ID '{'
coordinates=Xcoord
ports_connection+=Port*
input_position=InputPosition
testId=TestID
enableExpression=EnableExpression
('__PortSelect' '=' port_select=STRING ';')?
('__PortNumber' '=' port_value=INT ';')?
('__SyncPoint' '=' sync_point=BooleanType ';')?
('__Exec' '=' execution=ID ';')?
'}';
From this grammar I'm serializing an example file to xmi but my problem is that I'm not seeing the port_value element when its value is 0. Then, when I deserialize the xmi, I can't retrieve the same content as my original file because this field is missing.
This is my example file:
__SubFlow FtDualSupplyVmin_SubFlow {
__Node FT_DSVmin_Pass {
__XCoord = (1336,95);
__InputPosition = 279;
__TestID = "";
__EnableExpression = __Expression { __String = "TRUE"; __Type = BOOLEAN; }
__PortSelect = "0";
__PortNumber = 0;
}
}
And the associated xmi:
<?xml version="1.0" encoding="ASCII"?>
<unaDsl:UnaFile xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:unaDsl="http://www.mchp.com/dxfull/xtext/UnaDsl">
<una_elements xsi:type="unaDsl:SubFlow" name="FtDualSupplyVmin_SubFlow">
<elements xsi:type="unaDsl:Node" name="FT_DSVmin_Pass" port_select="0">
<coordinates x="1336" y="95"/>
<input_position position="279"/>
<testId name=""/>
<enableExpression>
<expr expr="TRUE" type="BOOLEAN"/>
</enableExpression>
</elements>
</una_elements>
</unaDsl:UnaFile>
In my xtend file where I have the code to serialize my file, I added the option OPTION_KEEP_DEFAULT_CONTENT but no change:
val Resource xmiResource = resourceSet.createResource(URI.createFileURI(xmiResourcePathName))
xmiResource.getContents().add(input.getContents().get(0))
var options = new HashMap<String, Object>();
options.put(XMIResource.OPTION_KEEP_DEFAULT_CONTENT, Boolean.TRUE);
xmiResource.save([b]options[/b])
Using the debugger I followed the code execution to find out where this parameter is filtered.
I found in the class org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl, the method saveFeatures() is going through all features and calls shouldSaveFeature().
protected boolean shouldSaveFeature(EObject o, EStructuralFeature f)
{
return o.eIsSet(f) || keepDefaults && f.getDefaultValueLiteral() != null;
}
keepDefaults is set to true thanks to the option OPTION_KEEP_DEFAULT_CONTENT but the feature getDefaultValueLiteral() method return null.
And the eIsSet() for my rule Node return false because it test the value of the object to its default value which is set to 0 in the generated NodeImpl.java file.
protected static final int PORT_VALUE_EDEFAULT = 0;
@Override
public boolean eIsSet(int featureID)
{
switch (featureID)
{
case UnaDslPackage.NODE__NAME:
return NAME_EDEFAULT == null ? name != null : !NAME_EDEFAULT.equals(name);
case UnaDslPackage.NODE__COORDINATES:
return coordinates != null;
case UnaDslPackage.NODE__PORTS_CONNECTION:
return ports_connection != null && !ports_connection.isEmpty();
case UnaDslPackage.NODE__INPUT_POSITION:
return input_position != null;
case UnaDslPackage.NODE__TEST_ID:
return testId != null;
case UnaDslPackage.NODE__ENABLE_EXPRESSION:
return enableExpression != null;
case UnaDslPackage.NODE__PORT_SELECT:
return PORT_SELECT_EDEFAULT == null ? port_select != null : !PORT_SELECT_EDEFAULT.equals(port_select);
case UnaDslPackage.NODE__PORT_VALUE:
return port_value != PORT_VALUE_EDEFAULT;
case UnaDslPackage.NODE__SYNC_POINT:
return SYNC_POINT_EDEFAULT == null ? sync_point != null : !SYNC_POINT_EDEFAULT.equals(sync_point);
case UnaDslPackage.NODE__EXECUTION:
return EXECUTION_EDEFAULT == null ? execution != null : !EXECUTION_EDEFAULT.equals(execution);
}
return super.eIsSet(featureID);
}
Is there a way to either change the NodeImpl to avoid having the default value tested ? Or to add a 'DefaultValueLiteral' in the EMF model ?
I hope I'm not mixing everything here, my knowledge on this is only practical, running the debugger to reverse engineer the behavior.
Thanks for any support on that.
Regards