working around Tuple22 limitation

Earlier this year I wrote about hitting some scala limitations:

Scala supports only up to Tuple22.

This means that Scala can define case classes only up to 22 parameters. I've implemented workarounds to use schema that includes complex types that has more than 22 particles within the sequence.

First, when a sequence contains more than MaxParticleSize (20) particles, it will split up the sequence into chunks of ChunkParticleSize (10). For example, a sequence that has 30 elements would be split into three chunks of 10 elements:

<xs:element name="foo">
  <xs:complexType>
   <xs:sequence>
     <xs:element name="string1" type="xs:string"/>
     <xs:element name="string2" type="xs:string"/>
     <xs:element name="string3" type="xs:string"/>
     ...
     <xs:element name="string30" type="xs:string"/>
   </xs:sequence>
  </xs:complexType>
</xs:element>

scalaxb converts the above element into as the following:

case class Foo(arg1: FooSequence2,
  arg2: FooSequence3,
  arg3: FooSequence4) {
  def string1 = arg1.string1
  def string2 = arg1.string2
  def string3 = arg1.string3
  def string4 = arg1.string4
  def string5 = arg1.string5
  def string6 = arg1.string6
  def string7 = arg1.string7
  def string8 = arg1.string8
  def string9 = arg1.string9
  def string10 = arg1.string10
  def string11 = arg2.string11
  def string12 = arg2.string12
  def string13 = arg2.string13
  def string14 = arg2.string14
  def string15 = arg2.string15
  def string16 = arg2.string16
  def string17 = arg2.string17
  def string18 = arg2.string18
  def string19 = arg2.string19
  def string20 = arg2.string20
  def string21 = arg3.string21
  def string22 = arg3.string22
  def string23 = arg3.string23
  def string24 = arg3.string24
  def string25 = arg3.string25
  def string26 = arg3.string26
  def string27 = arg3.string27
  def string28 = arg3.string28
  def string29 = arg3.string29
  def string30 = arg3.string30
}
 
case class FooSequence2(string1: String,
  string2: String,
  string3: String,
  string4: String,
  string5: String,
  string6: String,
  string7: String,
  string8: String,
  string9: String,
  string10: String)
 
case class FooSequence3(string11: String,
  string12: String,
  string13: String,
  string14: String,
  string15: String,
  string16: String,
  string17: String,
  string18: String,
  string19: String,
  string20: String)
 
case class FooSequence4(string21: String,
  string22: String,
  string23: String,
  string24: String,
  string25: String,
  string26: String,
  string27: String,
  string28: String,
  string29: String,
  string30: String)

Another way a complex type can go over 22 particles is by extension. XML Schema allows complex types to be extended from another similar to inheritance in type systems. On the other hand, inheritance of case classes does not work.

 <xs:complexType name="barOne">
   <xs:sequence>
     <xs:element name="int1" type="xs:int"/>
     <xs:element name="int2" type="xs:int"/>
     <xs:element name="int3" type="xs:int"/>
     <xs:element name="int4" type="xs:int"/>
     <xs:element name="int5" type="xs:int"/>
     <xs:element name="int6" type="xs:int"/>
     <xs:element name="int7" type="xs:int"/>
     <xs:element name="int8" type="xs:int"/>
     <xs:element name="int9" type="xs:int"/>
     <xs:element name="int10" type="xs:int"/>
   </xs:sequence>
 </xs:complexType>

 <xs:complexType name="barTwo">
   <xs:complexContent>
          <xs:extension base="barOne">
        <xs:sequence>
         <xs:element name="int11" type="xs:int"/>
         <xs:element name="int12" type="xs:int"/>
         <xs:element name="int13" type="xs:int"/>
         <xs:element name="int14" type="xs:int"/>
         <xs:element name="int15" type="xs:int"/>
         <xs:element name="int16" type="xs:int"/>
         <xs:element name="int17" type="xs:int"/>
         <xs:element name="int18" type="xs:int"/>
         <xs:element name="int19" type="xs:int"/>
         <xs:element name="int20" type="xs:int"/>
       </xs:sequence>
     </xs:extension>
   </xs:complexContent>
 </xs:complexType>

<xs:complexType name="barThree">
  <xs:complexContent>
         <xs:extension base="barTwo">
      <xs:sequence>
        <xs:element name="int21" type="xs:int"/>
        <xs:element name="int22" type="xs:int"/>
        <xs:element name="int23" type="xs:int"/>
        <xs:element name="int24" type="xs:int"/>
        <xs:element name="int25" type="xs:int"/>
        <xs:element name="int26" type="xs:int"/>
        <xs:element name="int27" type="xs:int"/>
        <xs:element name="int28" type="xs:int"/>
        <xs:element name="int29" type="xs:int"/>
        <xs:element name="int30" type="xs:int"/>
      </xs:sequence>
    </xs:extension>
  </xs:complexContent>
</xs:complexType>

Normally barThree will produce illegal case class with 30 parameters. The way to work around it is to wrap one of the complex type into a separate case class, but scalaxb wouldn't know which one. This is where --wrap-contents comes in. Using the option, we can specify which complex type to wrap using its name. The follow is generated by scalaxb with --wrap-contents BarOne:

case class BarThree(arg1: BarOnableSequence2,
  int11: Int,
  int12: Int,
  int13: Int,
  int14: Int,
  int15: Int,
  int16: Int,
  int17: Int,
  int18: Int,
  int19: Int,
  int20: Int,
  int21: Int,
  int22: Int,
  int23: Int,
  int24: Int,
  int25: Int,
  int26: Int,
  int27: Int,
  int28: Int,
  int29: Int,
  int30: Int) extends BarTwoable {
  def int1 = arg1.int1
  def int2 = arg1.int2
  def int3 = arg1.int3
  def int4 = arg1.int4
  def int5 = arg1.int5
  def int6 = arg1.int6
  def int7 = arg1.int7
  def int8 = arg1.int8
  def int9 = arg1.int9
  def int10 = arg1.int10
}