in daffodil-propgen/src/main/scala/org/apache/daffodil/propGen/PropertyGenerator.scala [189:307]
def genAttributeGroup(ag: Node): String = {
// val name = stripSuffix("AG", attr(ag, "name"))
val name =
attr(
ag,
"name"
).get // let's try leaving AG suffix in place so we can distinguish generated type mixins from AG mixins.
if (excludeType(name)) return ""
val subAgs = ag \ "attributeGroup"
val subRefAgs = subAgs.filter(ag => attr(ag, "ref") != None)
// val subNames = subRefAgs.map(ag => stripSuffix("AG", stripDFDLPrefix(attr(ag, "ref"))))
val subNames =
subRefAgs.map(ag => stripDFDLPrefix(attr(ag, "ref").get)) // leave AG suffix on.
assert(subAgs.length == subRefAgs.length) // "nested attributeGroup was not a reference"
val attribs = ag \ "attribute"
//
// for each attribute that is an Enum type, we want to use a Mixin of that type
//
val attribsNoDafRefs = attribs.flatMap { attrNode =>
val rawRef = attr(attrNode, "ref")
if (rawRef.isDefined) {
// this is referencing a Daffodil Extension, go find that attribute
if (rawRef.get.startsWith("daf:")) {
// ignore daf prefix and the dfdlx:Layer attribute group. These are
// duplicated in dfdlx for backwards compatability, so this ignores
// the duplicate.
None
} else {
val refWithoutPrefix = stripPrefix("dfdlx:", rawRef.get)
val dafAttrNode = (PropertyGenerator.daffodilExtensionsXML \ "attribute").find {
node =>
attr(node, "name").get == refWithoutPrefix
}.get
Some(dafAttrNode)
}
} else {
Some(attrNode)
}
}
val nonExcludedAttribs = attribsNoDafRefs.filter { attrNode =>
val rawName = attr(attrNode, "name").get
!excludeAttribute(rawName)
}
val (enumAttributeList, nonEnumAttributeList) = nonExcludedAttribs.partition { attrNode =>
{
val qualifiedTypeName = attr(attrNode, "type").get
val rawName = attr(attrNode, "name").get
val rawNameWithoutTextPrefix = stripPrefix("text", rawName)
val nameIsInTypeName =
qualifiedTypeName.toLowerCase.contains(rawNameWithoutTextPrefix.toLowerCase)
val endsInEnum = qualifiedTypeName.endsWith("Enum")
val res = endsInEnum && nameIsInTypeName
res
}
}
val enumList = enumAttributeList.map { attrNode =>
{
val qualifiedTypeName = attr(attrNode, "type").get
val enumName = stripSuffix("Enum", stripDFDLPrefix(qualifiedTypeName))
enumName
}
}
//
// for other attributes, we generate a member
//
val attrNamesTypes = nonEnumAttributeList.flatMap(attrNode => {
val rawName = attr(attrNode, "name").get
//
// exclude certain attribute names that aren't format properties
// We don't want properties for these.
val notFormatProperties =
List("ref", "type", "name", "test", "defaultValue", "message", "baseFormat")
val notScopedFormatProperties = List(
"inputValueCalc",
"outputValueCalc",
"hiddenGroupRef"
) // do these by-hand since they are not scoped.
val excludedBecauseDoneByHand =
List(
"runtimeProperties",
"separatorPolicy",
"separatorSuppressionPolicy",
"textOutputMinLength",
"textStandardExponentCharacter",
"textStandardExponentRep",
"textStandardInfinityRep",
"textStandardNaNRep",
"textStandardZeroRep",
"nilValue",
"textStringPadCharacter",
"textNumberPadCharacter",
"textBooleanPadCharacter",
"textCalendarPadCharacter"
)
val exclusions =
notFormatProperties ++ notScopedFormatProperties ++ excludedBecauseDoneByHand
if (exclusions.contains(rawName)) {
Nil
} else {
val name = if (isScalaKeyword(rawName)) rawName + "_" else rawName
val qualifiedTypeName = attr(attrNode, "type").get
// we still might have some enums here, because we exclude enums above that
// aren't matching the name of the attribute. (e.g., if we have an attribute which has type YesNo, then
// that will show up as a YesNoEnum here.
val typeName = stripSuffix("Enum", stripDFDLPrefix(qualifiedTypeName))
// val typeName = stripDFDLPrefix(qualifiedTypeName) // leave suffix on.
List((name, typeName))
}
})
val res = generatePropertyGroup(name, attrNamesTypes, subNames, enumList)
val block = comment(ag) + res + sep
block
}