} // else (recIdentMethod.equals("TypeIdentifier"))
String[] recordTypeNames = new String[numOfRecordTypes];
// Storing the names for consistency check gainst the record type
// specification section.
LinkedList typeIds = new LinkedList();
LinkedList typeIdIntervals = new LinkedList();
// Record type identifier may be single values or intervals.
// They are stored to check their unique reference to a record type.
int recordTypesCount = recordTypes.getLength();
// the number of record types in the current record group or at all
// (wihtout grouping) - at least if no bad nodes are included in a
// errorprone specification
int recordTypesBefore = 0;
// number of record type declarations checked in other record groups
// before - used as offset to datermine the position in the record type
// array
while (recordGroup != null)
{ // loop over record groups
// - only one loop if <recOrder>!="Structured" because of missing
// record groups
for (int i = 0; i < recordTypesCount; i++)
{ // Loop over all record type declarations of the record group
Node rType = recordTypes.item(i);
// Extension if no DTD validating
if (rType.getNodeType() != Node.ELEMENT_NODE
|| !rType.getNodeName().equals("RecordType"))
{
List params = new Vector();
params.add(rType.getNodeName());
throw new XException(Constants.LOCATION_INTERN,
Constants.LAYER_PROTOCOL,
Constants.PACKAGE_PROTOCOL_RECORDS, "15", params);
}
// Check the consistency of this single record type declaration.
// If its occurrence depends on values in the prececeeding
// record
// the information about this value is stored in
// <dependenceOnPredecessor>.
String[] dependenceOnPredecessor = checkRecordTypeDeclaration(
rType, recordTypesCount, recordTypesBefore + i,
recIdentMethod, recOrder, recordTypeNames, typeIds,
typeIdIntervals, existanceIndicators);
if (existanceIndicators != null
&& dependenceOnPredecessor != null)
{ // Existance records are expected in general and an
// existance
// indicator is defined for the last cheched record type.
// To ensure that the identification via existance
// indicators
// is possible, the information about them is analysed the
// other
// way round. Originally the information was attached as
// <dependenceOnPredecessor> to the dependent record type.
// Now it will be attached as <existanceIndicators> to its
// possible predecessors.
String occurrences = ((Element) recordTypes.item(i))
.getAttribute("Occurrences");
// Cardinality of the record type.
boolean isOptional = CardinalityStrings
.isCardinalityInterval(occurrences, true)
&& CardinalityStrings.getCardinalityLow(
occurrences, true) == 0;
for (int j = i - 1; j > -1 && isOptional; j++)
{ // Backwards loop to the beginning of the record types
// starting at the predecessor of the examined record
// type.
// As long as a record type is optional, its predecessor
// is
// added to the list of possible predecessors for the
// originally
// checked record type.
// Stops at the first record type because this one may
// not be optional.
// Now information attached to the predecessor.
if (existanceIndicators[j] == null)
{ // The predecessor does not yet have identified
// successor
// which depend on an existnace indicator.
existanceIndicators[j] = new TreeMap();
existanceIndicators[j].put(
dependenceOnPredecessor[0],
dependenceOnPredecessor[1]);
} // then (existanceIndicators[j]==null)
else
{ // The predecessor already has information about
// successors.
// Existance indicator value for the existance
// indicator
// field stated in the examined record type, but
// used for
// another record type !?
String value = (String) existanceIndicators[j]
.get(dependenceOnPredecessor[0]);
if (value != null)
// Existance indicator values in the same field
// for different record types.
if (value.length() != dependenceOnPredecessor[1]
.length())
{
throw new XException(
Constants.LOCATION_INTERN,
Constants.LAYER_PROTOCOL,
Constants.PACKAGE_PROTOCOL_RECORDS,
"16");
}
else
// No other use of the existance indicator
// field yet.
// Store the new value.
existanceIndicators[j].put(
dependenceOnPredecessor[0],
dependenceOnPredecessor[1]);
} // else (existanceIndicators[j]==null)
occurrences = ((Element) recordTypes.item(j))
.getAttribute("Occurrences");
// Cardinality of the last checked record type
isOptional = CardinalityStrings.isCardinalityInterval(
occurrences, true)
&& CardinalityStrings.getCardinalityLow(
occurrences, true) == 0;
} // for (int j=i-1; j>-1 && isOptional; j++)
} // if (existanceIndicators!=null &&
// dependenceOnPredecessor!=null)
} // for (int i=0; i<recordTypes.getLength(); i++)
recordTypesBefore += recordTypesCount;
// Correct the number of checked record types in the so far
// examined record groups
if (recordGroup.getNodeName().equals("RecordGroup"))
{ // record groups really present
recordGroup = recordGroup.getNextSibling();
// Choose next record group
if (recordGroup != null)
{ // there is a next record group
recordTypes = recordGroup.getChildNodes();
recordTypesCount = recordTypes.getLength();
// Next check the record types in the new group
} // if (recordGroup != null)
} // if (recordGroup.getNodeName().equals("RecordGroup"))
else
// no real record group loop but record declarations directly
// in lines section, terminate loop by setting ...
recordGroup = null;
} // while (recordGroup!=null) - record group loop
// Check record type names for uniqueness.
for (int i = 0; i < recordTypeNames.length; i++)
for (int j = i + 1; j < recordTypeNames.length; j++)
if (recordTypeNames[i].equals(recordTypeNames[j]))
{
throw new XException(Constants.LOCATION_INTERN,
Constants.LAYER_PROTOCOL,
Constants.PACKAGE_PROTOCOL_RECORDS, "17");
}
// Checks on the type identifier
// First check their length
// If the record type identification is not done by type identifiers,
// the two type id lists are empty.
int identifierLength = 0;
if (typeIds.size() > 0)
// Some single value id's
identifierLength = ((String) typeIds.get(0)).length();
else if (typeIdIntervals.size() > 0)
// No single value id but some id intervals
identifierLength = ((String[]) typeIdIntervals.get(0))[0].length();
// All id's must have the same length.
// First the single value id's
for (int i = 1; i < typeIds.size(); i++)
if (((String) typeIds.get(0)).length() != identifierLength)
{
throw new XException(Constants.LOCATION_INTERN,
Constants.LAYER_PROTOCOL,
Constants.PACKAGE_PROTOCOL_RECORDS, "18");
}
// Second the id intervals
for (int i = 1; i < typeIdIntervals.size(); i++)
// Attention: two values!
if (((String[]) typeIdIntervals.get(0))[0].length() != identifierLength
|| ((String[]) typeIdIntervals.get(0))[1].length() != identifierLength)
{
throw new XException(Constants.LOCATION_INTERN,
Constants.LAYER_PROTOCOL,
Constants.PACKAGE_PROTOCOL_RECORDS, "18");
}