use of org.eclipse.titan.designer.AST.TTCN3.attributes.ErroneousAttributeSpecification.Indicator_Type in project titan.EclipsePlug-ins by eclipse.
the class ErroneousAttributes method buildErroneousDescriptorTree.
private ErroneousDescriptor buildErroneousDescriptorTree(final CompilationTimeStamp timestamp, final List<FieldErr_Type> fldArray, final int level) {
final ErroneousDescriptor erroneousDescr = new ErroneousDescriptor();
Qualifier omitBeforeQualifier = null;
Qualifier omitAfterQualifier = null;
final Map<Integer, List<FieldErr_Type>> embeddedFieldArrayMap = new HashMap<Integer, List<FieldErr_Type>>();
for (FieldErr_Type actualFieldErr : fldArray) {
if (actualFieldErr.subrefsArray.size() <= level) {
ErrorReporter.INTERNAL_ERROR();
return erroneousDescr;
}
final int fieldIndex = actualFieldErr.subrefsArray.get(level);
final IType fieldType = actualFieldErr.typeArray.get(level);
if (omitBeforeQualifier != null && erroneousDescr.omitBefore != -1 && erroneousDescr.omitBefore > fieldIndex) {
final String message = MessageFormat.format("Field `{0}'' cannot be referenced because all fields before field `{1}'' have been omitted", actualFieldErr.qualifier.getDisplayName(), omitBeforeQualifier.getDisplayName());
actualFieldErr.qualifier.getLocation().reportSemanticError(message);
continue;
}
if (omitAfterQualifier != null && erroneousDescr.omitAfter != -1 && erroneousDescr.omitAfter < fieldIndex) {
final String message = MessageFormat.format("Field `{0}'' cannot be referenced because all fields after field `{1}'' have been omitted", actualFieldErr.qualifier.getDisplayName(), omitAfterQualifier.getDisplayName());
actualFieldErr.qualifier.getLocation().reportSemanticError(message);
continue;
}
final Indicator_Type actIndicator = actualFieldErr.errAttrSpec.getIndicator();
final boolean isOmit = actualFieldErr.errAttrSpec.isOmit();
if (actualFieldErr.subrefsArray.size() == level + 1) {
// erroneous value
if (actualFieldErr.typeArray.size() != level + 1) {
ErrorReporter.INTERNAL_ERROR();
return erroneousDescr;
}
if (fieldType.getTypetype() == Type_type.TYPE_ASN1_SET && isOmit && actIndicator != Indicator_Type.Value_Indicator) {
final String message = MessageFormat.format("Cannot omit all fields {0} `{1}'' which is a field of an ASN.1 SET type. " + "The order of fields in ASN.1 SET types changes depending on tagging (see X.690 9.3). " + "Fields can be omitted individually, independently of the field order which depends on tagging", actIndicator.getDisplayName(), actualFieldErr.qualifier.getDisplayName());
actualFieldErr.qualifier.getLocation().reportSemanticError(message);
continue;
}
switch(fieldType.getTypetypeTtcn3()) {
case TYPE_TTCN3_CHOICE:
if (actIndicator != Indicator_Type.Value_Indicator) {
final String message = MessageFormat.format("Indicator `{0}'' cannot be used with reference `{1}'' which points to a field of a union type", actIndicator.getDisplayName(), actualFieldErr.qualifier.getDisplayName());
actualFieldErr.qualifier.getLocation().reportSemanticError(message);
continue;
}
break;
case TYPE_TTCN3_SEQUENCE:
case TYPE_TTCN3_SET:
if (isOmit && actIndicator == Indicator_Type.After_Indicator) {
int lastFieldIndex;
switch(fieldType.getTypetype()) {
case TYPE_ASN1_SEQUENCE:
lastFieldIndex = ((ASN1_Sequence_Type) fieldType).getNofComponents(timestamp) - 1;
break;
case TYPE_ASN1_SET:
lastFieldIndex = ((ASN1_Set_Type) fieldType).getNofComponents(timestamp) - 1;
break;
default:
lastFieldIndex = ((TTCN3_Set_Seq_Choice_BaseType) fieldType).getNofComponents() - 1;
}
if (fieldIndex == lastFieldIndex) {
final String message = MessageFormat.format("There is nothing to omit after the last field ({0}) of a record/set type", actualFieldErr.qualifier.getDisplayName());
actualFieldErr.qualifier.getLocation().reportSemanticError(message);
continue;
}
}
// $FALL-THROUGH$
case TYPE_SEQUENCE_OF:
case TYPE_SET_OF:
if (isOmit && actIndicator == Indicator_Type.Before_Indicator && fieldIndex == 0) {
actualFieldErr.qualifier.getLocation().reportSemanticError(MessageFormat.format("There is nothing to omit before the first field ({0})", actualFieldErr.qualifier.getDisplayName()));
continue;
}
break;
default:
break;
}
// check for duplicate value+indicator
if (erroneousDescr.valuesMap.containsKey(fieldIndex)) {
final ErroneousValues evs = erroneousDescr.valuesMap.get(fieldIndex);
if ((evs.before != null && actIndicator == Indicator_Type.Before_Indicator) || (evs.value != null && actIndicator == Indicator_Type.Value_Indicator) || (evs.after != null && actIndicator == Indicator_Type.After_Indicator)) {
actualFieldErr.qualifier.getLocation().reportSemanticError(MessageFormat.format("Duplicate reference to field `{0}'' with indicator `{1}''", actualFieldErr.qualifier.getDisplayName(), actIndicator.getDisplayName()));
continue;
}
}
// values were used
if (actIndicator == Indicator_Type.Value_Indicator && embeddedFieldArrayMap.containsKey(fieldIndex)) {
final String message = MessageFormat.format("Reference to field `{0}'' with indicator `value'' would invalidate previously specified erroneous data", actualFieldErr.qualifier.getDisplayName());
actualFieldErr.qualifier.getLocation().reportSemanticError(message);
continue;
}
// duplication of omit before/after rule
if (actIndicator == Indicator_Type.Before_Indicator && isOmit) {
if (omitBeforeQualifier != null && erroneousDescr.omitBefore != -1) {
final String message = MessageFormat.format("Duplicate rule for omitting all fields before the specified field. " + "Used on field `{0}'' but previously already used on field `{1}''", actualFieldErr.qualifier.getDisplayName(), omitBeforeQualifier.getDisplayName());
actualFieldErr.qualifier.getLocation().reportSemanticError(message);
continue;
}
boolean isInvalid = false;
for (Integer idx : erroneousDescr.valuesMap.keySet()) {
if (idx < fieldIndex) {
isInvalid = true;
break;
}
}
if (!isInvalid) {
for (Integer idx : embeddedFieldArrayMap.keySet()) {
if (idx < fieldIndex) {
isInvalid = true;
break;
}
}
}
if (isInvalid) {
final String message = MessageFormat.format("Omitting fields before field `{0}'' would invalidate previously specified erroneous data", actualFieldErr.qualifier.getDisplayName());
actualFieldErr.qualifier.getLocation().reportSemanticError(message);
continue;
}
// save valid omit before data
omitBeforeQualifier = actualFieldErr.qualifier;
erroneousDescr.omitBefore = fieldIndex;
erroneousDescr.omitBeforeName = omitBeforeQualifier.getDisplayName();
continue;
}
if (actIndicator == Indicator_Type.After_Indicator && isOmit) {
if (omitAfterQualifier != null && erroneousDescr.omitAfter != -1) {
final String message = MessageFormat.format("Duplicate rule for omitting all fields after the specified field. " + "Used on field `{0}'' but previously already used on field `{1}''", actualFieldErr.qualifier.getDisplayName(), omitAfterQualifier.getDisplayName());
actualFieldErr.qualifier.getLocation().reportSemanticError(message);
continue;
}
boolean isInvalid = false;
for (Integer idx : erroneousDescr.valuesMap.keySet()) {
if (idx > fieldIndex) {
isInvalid = true;
break;
}
}
if (!isInvalid) {
for (Integer idx : embeddedFieldArrayMap.keySet()) {
if (idx > fieldIndex) {
isInvalid = true;
break;
}
}
}
if (isInvalid) {
final String message = MessageFormat.format("Omitting fields after field `{0}'' would invalidate previously specified erroneous data", actualFieldErr.qualifier.getDisplayName());
actualFieldErr.qualifier.getLocation().reportSemanticError(message);
continue;
}
// save valid omit after data
omitAfterQualifier = actualFieldErr.qualifier;
erroneousDescr.omitAfter = fieldIndex;
erroneousDescr.omitAfterName = omitAfterQualifier.getDisplayName();
continue;
}
// if not before/after omit then save this into
// values_m
final boolean hasKey = erroneousDescr.valuesMap.containsKey(fieldIndex);
final ErroneousValues evs = hasKey ? erroneousDescr.valuesMap.get(fieldIndex) : new ErroneousValues(actualFieldErr.qualifier.getDisplayName());
switch(actIndicator) {
case Before_Indicator:
evs.before = actualFieldErr.errAttrSpec;
break;
case Value_Indicator:
evs.value = actualFieldErr.errAttrSpec;
break;
case After_Indicator:
evs.after = actualFieldErr.errAttrSpec;
break;
default:
ErrorReporter.INTERNAL_ERROR();
}
if (!hasKey) {
erroneousDescr.valuesMap.put(fieldIndex, evs);
}
} else {
// embedded err.value
if (erroneousDescr.valuesMap.containsKey(fieldIndex) && erroneousDescr.valuesMap.get(fieldIndex).value != null) {
final String message = MessageFormat.format("Field `{0}'' is embedded into a field which was previously overwritten or omitted", actualFieldErr.qualifier.getDisplayName());
actualFieldErr.qualifier.getLocation().reportSemanticError(message);
continue;
}
// add the embedded field to the map
final boolean hasIndex = embeddedFieldArrayMap.containsKey(fieldIndex);
final List<FieldErr_Type> embeddedFieldArray = hasIndex ? embeddedFieldArrayMap.get(fieldIndex) : new ArrayList<FieldErr_Type>(1);
embeddedFieldArray.add(actualFieldErr);
if (!hasIndex) {
embeddedFieldArrayMap.put(fieldIndex, embeddedFieldArray);
}
}
}
// recursive calls to create embedded descriptors
for (Integer idx : embeddedFieldArrayMap.keySet()) {
erroneousDescr.descriptorMap.put(idx, buildErroneousDescriptorTree(timestamp, embeddedFieldArrayMap.get(idx), level + 1));
}
return erroneousDescr;
}
Aggregations