class RecordStructureDeclarationRules extends TimedDelegate {

    @Override
    protected Set<Violation> doMeasuredAnalysis() throws JDOMException {
        final Set<Violation> violations = new HashSet<Violation>();

        final List<Element> records = selectNodesByName("RECORD.");
        final List<Element> frees = selectNodesByName("Z_FREE.");

        for (final Element record : records) {
            final String recordName = getCclName(record.getChild("COMMA."));

            // Identify all fields within the record that appear to be lists or structures
            for (final Element listOrStruct : selectNodesByName(record, "FIELD.", "[OCCUR. or not(FORMAT.)]")) {
                if (listOrStruct.getChildren("FIELD.").size() == 0) {
                    violations.add(new EmptyListOrStructureDefinitionViolation(recordName, getCclName(listOrStruct),
                            getLineNumber(listOrStruct)));
                }
            }

            // If record structure is declared and not protected, then add the violation
            if (recordStructureHasNoDefinedScoping(record)) {
                violations.add(new UnprotectedRecordStructureDefinitionViolation(recordName, getLineNumber(record)));
            }

            // search for an instance where a defined record is freed and add the violation
            for (final Element free : frees) {
                if (getCclName(free).equalsIgnoreCase(recordName)) {
                    violations.add(new FreedRecordStructureViolation(recordName, getLineNumber(free)));
                    break;
                }
            }
        }

        return violations;
    }

    public  RecordStructureDeclarationRules(final Document document);

}