Tuple22 限界への対策
今年の初めに Scala の限界に関して書きました:
Scala は
Tuple22
までしかサポートしません.
これは Scala が 22個のパラメータを超えた case class を定義できないことを意味します.22個を超えたパーティクルを持つシーケンスを含む複合型を定義するスキーマを扱えるよう回避策をいくつか用意しました.
まず,シーケンスが MaxParticleSize
(20)個以上のパーティクルを持つとき,シーケンスを ChunkParticleSize
(10)個ごとのチャンク(塊)に分けることにしました.例えば,30個の要素を持つシーケンスは 10個づつの要素を持った三つのチャンクに分かれます:
<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 は以上の要素から以下のコードを生成します:
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)
拡張によって複合型が 22個のパーティクルを超えることがあります.XML Schema は型システムの継承に似て,複合型を他の型から拡張することができます.一方,case class を継承することはできません.
<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>
通常 barThree
は 30個のパラメータを持った違法な case class を生成します.複合型の一つを別の case class に追い出すことで回避することができますが,scalaxb はどれを選ぶかを知り得ません.ここで登場するのが --wrap-contents
です.このオプションを使うことでどの複合型を追い出すかを指定することができます.以下が --wrap-contents BarOne
を使って scalaxb によって生成したものです:
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 }