Description
There are quite a few places where scala match-case logic is used in the daffodil schema compiler. This is typical of compilers, in that they often have algorithms that operate over a number of types that benefit from keeping the whole algorithm in one class.
The scala compiler will produce valuable warnings that improve maintainability of the code if the types involved in the case analysis are sealed - that is, if the scala compiler knows the complete set of possibilities.
The DSOM types can be refactored so that the primary traits/classes used in case statements are all in one file where they can all be sealed, enabling the scala compiler's checking.
These classes/traits are large and rich, so their definitions do not all want to be centralized into that one file.
Hence, each DSOM type that ultimately derives from SchemaComponent should be split into a "Primary" trait that lives in the existing file, and a part that lives in a new central file for the sealed traits/classes. Using ElementBase as an example, the centralized file will have
sealed abstract class ElementBase(....) extends Term(....) with ElementBasePrimaryMixin
And the existing ElementBase.scala file would have:
final trait ElementBasePrimaryMixin extends ... list of everything already in the extends of ElementBase.... { self : ElementBase => .... all existing contents of ElementBase class }
This enables us to also cleanup the schema compiler in that we can insure the traits/classes defined in the centralized file are all properly named so that those are the only traits/classes one uses in case statements. I.e., use of traits/classes whose names end in "...Mixin" would be exclusively in the extends-with clauses of trait/class definitions, and not in case analysis.