I'm making a p:dataTable for users' ip ranges with cellEditors, which consist of p:inputMask. The dataTable consists of 2 editable columns. To validate I have to:
- Check whether the specified ip-adress matches the RegEx,
- Ensure that start of the range is actually before than the finish,
- Ensure that specified range is not intersecting with previously entered ranges.
First two parts didn't make much noise. The third one required me to check if the specified range is before or after previously entered ranges. You just check start and finish to be both either before or after every other ip range. Easy, right?
The validating cycle.
for (Groupip gip : searchResults) {
long ipend = ipToLong(InetAddress.getByName(gip.getIpend()));
long ipstart = ipToLong(InetAddress.getByName(gip.getIpstart()));
boolean validLeft = true, validRight = true;
validLeft = validLeft && ipstart < ipValidated;
validLeft = validLeft && ipend < ipValidated;
validLeft = validLeft && ipstart < ipValidating;
validLeft = validLeft && ipend < ipValidating;
validRight = validRight && ipstart > ipValidated;
validRight = validRight && ipend > ipValidated;
validRight = validRight && ipstart > ipValidating;
validRight = validRight && ipend > ipValidating;
if (validLeft || validRight) {
//OK
} else {
//ERROR
}
}
The dataTable.
<p:dataTable id="ips1" widgetVar="ips1" var="ip" value="#{groupipController.searchResults}" editable="true"
rowKey="#{ip.groupcode}-#{ip.ipstart}-#{ip.ipend}" selection="#{groupipController.selected}" selectionMode="single"
>
<f:facet name="header">
Диапазон IP
</f:facet>
<p:ajax event="rowEditCancel" listener="#{groupipController.onRowCancel}" />
<p:ajax event="rowEditInit" listener="#{groupipController.onRowEditInit}" />
<p:ajax event="rowEdit" listener="#{groupipController.onRowEdit}" update=":form:msgs :form:ips1 :form:growlmsgs" process=":form:ips1"/>
<p:column headerText="От" style="min-height: 16px" id='from_col'>
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{ip.ipstart}" /></f:facet>
<f:facet name="input">
<p:inputMask mask="999.999.999.999" value="#{ip.ipstart}" id="fromip" autoClear="false" slotChar="0"
validator="#{groupipController.validate}"
class="ui-inputfield ui-inputmask ui-widget ui-state-default ui-corner-all p-0-1 w-100 h-100"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="До" style="min-height: 16px" id='to_col'>
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{ip.ipend}" /></f:facet>
<f:facet name="input">
<p:inputMask mask="999.999.999.999" value="#{ip.ipend}" id="toip" autoClear="false" slotChar="0"
validator="#{groupipController.validate}"
class="ui-inputfield ui-inputmask ui-widget ui-state-default ui-corner-all p-0-1 w-100 h-100"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column width="10%" >
<p:rowEditor rendered="#{armgroupController.update}" />
</p:column>
</p:dataTable>
But there is more. The searchResults
is a variable, which is the source for dataTable, that contains a List<Groupip>
. But it also contains the row that is currently being edited. So I have to exclude it, or I will fail the validation, comparing the range to itself.
How do I do this exactly? The only way I could find the row index of the editting row is to get the pre-last value of the cliendId (which looks like this in the browser: form:ips1:2:toip
) with this code:
if (gip == searchResults.get(Integer.parseInt(component.getClientId().split(":")[2]))) {
continue;
}
This is not appropriate, since naming containers could change. So, I would like to know, is there another way to get row index?