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
}