@@ -630,7 +630,7 @@ private void validateTypeAndRequired(Bind bind, int position, Set<String> invali
// Don't try to apply validity to a node if it has children nodes or if it's not a node
// "The type model item property is not applied to instance nodes that contain child elements"
final Bind . BindNode bindNode = bind .getBindNode (position );
final BindNode bindNode = bind .getBindNode (position );
final NodeInfo currentNodeInfo = bindNode .nodeInfo ;
if (currentNodeInfo == null || bindNode .hasChildrenElements )
return ;
@@ -690,7 +690,8 @@ private void validateTypeAndRequired(Bind bind, int position, Set<String> invali
// Remember invalid instances
if (!typeValidity || !requiredValidity ) {
final XFormsInstance instanceForNodeInfo = containingDocument .getInstanceForNode (currentNodeInfo );
invalidInstances .add (instanceForNodeInfo .getEffectiveId ());
if (instanceForNodeInfo != null )
invalidInstances .add (instanceForNodeInfo .getEffectiveId ());
}
}
@@ -699,7 +700,7 @@ private void validateConstraint(Bind bind, int position, Set<String> invalidInst
assert bind .staticBind .getConstraint () != null ;
// Don't try to apply validity to a node if it's not a node
final Bind . BindNode bindNode = bind .getBindNode (position );
final BindNode bindNode = bind .getBindNode (position );
final NodeInfo currentNodeInfo = bindNode .nodeInfo ;
if (currentNodeInfo == null )
return ;
@@ -927,7 +928,7 @@ public Bind(BindTree.Bind staticBind, boolean isSingleNodeContext) {
{
// Create iteration and remember it
final boolean isNewSingleNodeContext = isSingleNodeContext && nodesetSize == 1 ;
final BindIteration currentBindIteration = new BindIteration (isNewSingleNodeContext , item , childrenStaticBinds );
final BindIteration currentBindIteration = new BindIteration (getStaticId (), isNewSingleNodeContext , item , childrenStaticBinds , typeQName );
bindNodes .add (currentBindIteration );
// Create mapping context node -> iteration
@@ -948,7 +949,7 @@ public Bind(BindTree.Bind staticBind, boolean isSingleNodeContext) {
bindNodes = new ArrayList <BindNode >(nodesetSize );
for (final Item item : nodeset )
bindNodes .add (new BindNode (item ));
bindNodes .add (new BindNode (getStaticId (), item , typeQName ));
}
}
@@ -1044,128 +1045,130 @@ public boolean isValid(int position) {
return getBindNode (position ).isValid ();
}
// BindNode holds MIP values for a given bind node
public class BindNode {
// Current MIP state
private boolean relevant = Model .DEFAULT_RELEVANT ();
protected boolean readonly = Model .DEFAULT_READONLY ();
private boolean required = Model .DEFAULT_REQUIRED ();
private Map <String , String > customMips = null ;
private boolean typeValidity = Model .DEFAULT_VALID ();
private boolean requiredValidity = Model .DEFAULT_VALID ();
private boolean constraintValidity = Model .DEFAULT_VALID ();
public final NodeInfo nodeInfo ;
public final boolean hasChildrenElements ;
private BindNode (Item item ) {
if (item instanceof NodeInfo ) {
nodeInfo = (NodeInfo ) item ;
hasChildrenElements = nodeInfo .getNodeKind () == org .w3c .dom .Document .ELEMENT_NODE && XML .hasChildElement (nodeInfo );
// Add us to the node
InstanceData .addBindNode (nodeInfo , this );
if (Bind .this .typeQName != null )
InstanceData .setBindType (nodeInfo , Bind .this .typeQName );
} else {
nodeInfo = null ;
hasChildrenElements = false ;
}
}
// Bind node that also contains nested binds
private class BindIteration extends BindNode {// TODO: if bind doesn't have MIPs, BindNode storage is not needed
public String getBindStaticId () {
return Bind .this .getStaticId ();
}
private List <Bind > childrenBinds ;
public void setRelevant (boolean value ) {
this .relevant = value ;
}
public BindIteration (String bindStaticId , boolean isSingleNodeContext , Item item , List <BindTree .Bind > childrenStaticBinds , QName typeQName ) {
public void setReadonly (boolean value ) {
this .readonly = value ;
}
super (bindStaticId , item , typeQName );
public void setRequired (boolean value ) {
this .required = value ;
}
assert childrenStaticBinds .size () > 0 ;
public void setCustom ( String name , String value ) {
if ( customMips == null )
customMips = new HashMap < String , String >(); // maybe should be LinkedHashMap for reproducibility
customMips . put ( name , value );
// Iterate over children and create children binds
childrenBinds = new ArrayList < Bind >( childrenStaticBinds . size ());
for ( final BindTree . Bind staticBind : childrenStaticBinds )
childrenBinds . add ( new Bind ( staticBind , isSingleNodeContext ) );
}
public void setTypeValidity (boolean value ) {
this .typeValidity = value ;
public void applyBinds (BindRunner bindRunner ) {
for (final Bind currentBind : childrenBinds )
currentBind .applyBinds (bindRunner );
}
public void setRequiredValidity (boolean value ) {
this .requiredValidity = value ;
public Bind getBind (String bindId ) {
for (final Bind currentBind : childrenBinds )
if (currentBind .staticBind .staticId ().equals (bindId ))
return currentBind ;
return null ;
}
}
}
public void setConstraintValidity (boolean value ) {
this .constraintValidity = value ;
// BindNode holds MIP values for a given bind node
public static class BindNode {
// Current MIP state
private boolean relevant = Model .DEFAULT_RELEVANT ();
protected boolean readonly = Model .DEFAULT_READONLY ();
private boolean required = Model .DEFAULT_REQUIRED ();
private Map <String , String > customMips = null ;
private boolean typeValidity = Model .DEFAULT_VALID ();
private boolean requiredValidity = Model .DEFAULT_VALID ();
private boolean constraintValidity = Model .DEFAULT_VALID ();
public final String bindStaticId ;
public final NodeInfo nodeInfo ;
public final boolean hasChildrenElements ;
public BindNode (String bindStaticId , Item item , QName typeQName ) {
this .bindStaticId = bindStaticId ;
if (item instanceof NodeInfo ) {
nodeInfo = (NodeInfo ) item ;
hasChildrenElements = nodeInfo .getNodeKind () == org .w3c .dom .Document .ELEMENT_NODE && XML .hasChildElement (nodeInfo );
// Add us to the node
InstanceData .addBindNode (nodeInfo , this );
if (typeQName != null )
InstanceData .setBindType (nodeInfo , typeQName );
} else {
nodeInfo = null ;
hasChildrenElements = false ;
}
}
public boolean isRelevant () {
return relevant ;
}
public String getBindStaticId () {
return bindStaticId ;
}
public boolean isReadonly ( ) {
return readonly ;
}
public void setRelevant ( boolean value ) {
this . relevant = value ;
}
public boolean isRequired ( ) {
return required ;
}
public void setReadonly ( boolean value ) {
this . readonly = value ;
}
public boolean isValid ( ) {
return typeValidity && requiredValidity && constraintValidity ;
}
public void setRequired ( boolean value ) {
this . required = value ;
}
public boolean isTypeValid () {
return typeValidity ;
}
public void setCustom (String name , String value ) {
if (customMips == null )
customMips = new HashMap <String , String >(); // maybe should be LinkedHashMap for reproducibility
customMips .put (name , value );
}
public boolean isConstraintValidity ( ) {
return constraintValidity ;
}
public void setTypeValidity ( boolean value ) {
this . typeValidity = value ;
}
public Map <String , String > getCustomMips () {
return customMips == null ? null : Collections .unmodifiableMap (customMips );
}
public void setRequiredValidity (boolean value ) {
this .requiredValidity = value ;
}
// Bind node that also contains nested binds
private class BindIteration extends BindNode {// TODO: if bind doesn't have MIPs, BindNode storage is not needed
public void setConstraintValidity (boolean value ) {
this .constraintValidity = value ;
}
private List <Bind > childrenBinds ;
public boolean isRelevant () {
return relevant ;
}
public BindIteration (boolean isSingleNodeContext , Item item , List <BindTree .Bind > childrenStaticBinds ) {
public boolean isReadonly () {
return readonly ;
}
super (item );
public boolean isRequired () {
return required ;
}
assert childrenStaticBinds .size () > 0 ;
public boolean isValid () {
return typeValidity && requiredValidity && constraintValidity ;
}
// Iterate over children and create children binds
childrenBinds = new ArrayList <Bind >(childrenStaticBinds .size ());
for (final BindTree .Bind staticBind : childrenStaticBinds )
childrenBinds .add (new Bind (staticBind , isSingleNodeContext ));
}
public boolean isTypeValid () {
return typeValidity ;
}
public void applyBinds (BindRunner bindRunner ) {
for (final Bind currentBind : childrenBinds )
currentBind .applyBinds (bindRunner );
}
public boolean isConstraintValidity () {
return constraintValidity ;
}
public Bind getBind (String bindId ) {
for (final Bind currentBind : childrenBinds )
if (currentBind .staticBind .staticId ().equals (bindId ))
return currentBind ;
return null ;
}
public Map <String , String > getCustomMips () {
return customMips == null ? null : Collections .unmodifiableMap (customMips );
}
}
}