Skip to content

Instantly share code, notes, and snippets.

@honnix
Created November 24, 2010 13:25
Show Gist options
  • Save honnix/713648 to your computer and use it in GitHub Desktop.
Save honnix/713648 to your computer and use it in GitHub Desktop.
transform ASN.1 module into xml schema
package com.ericsson.asn12schema.transformer
import scala.xml.{UnprefixedAttribute, Null}
import com.honnix.asn12schema.model.datatype.complex.{ASN1EnumeratedType, ASN1SetField, ASN1SetOfType, ASN1SetType}
import com.honnix.asn12schema.model.ASN1Module
import com.honnix.asn12schema.model.datatype.primitive.{ASN1PrimitiveType, ASN1BooleanType, ASN1IA5StringType, ASN1IntegerType}
class DefaultTransformer extends Transformer {
private def dealWithIntOrString(field: ASN1SetField) = {
val t = field.dataType.asInstanceOf[ASN1PrimitiveType]
val defaultOrNull = if (t.default.isEmpty) Null else new UnprefixedAttribute("default", t.default.get.toString, Null)
val schemaType = if (t.isInstanceOf[ASN1IntegerType]) "xs:integer" else "xs:string"
if (t.hasRange)
if (field.identifier)
<xs:element name={field.name} type={field.name + field.mySet.name + "IdentifierType"} minOccurs={if (field.mandatory) "1" else "0"} /> % defaultOrNull
else
<xs:element name={field.name} minOccurs={if (field.mandatory) "1" else "0"}>
<xs:simpleType>
<xs:restriction base={schemaType}> {
if (t.isInstanceOf[ASN1IntegerType]) {
val tmp = t.asInstanceOf[ASN1IntegerType]
if (tmp.minVal != Int.MinValue) <xs:minInclusive value={tmp.minVal.toString} /> else Null
if (tmp.maxVal != Int.MaxValue) <xs:maxInclusive value={tmp.maxVal.toString} /> else Null
} else {
val tmp = t.asInstanceOf[ASN1IA5StringType]
if (tmp.minLen != 0) <xs:minLength value={tmp.minLen.toString} /> else Null
if (tmp.maxLen != Int.MaxValue) <xs:maxLength value={tmp.maxLen.toString} /> else Null
}
}
</xs:restriction>
</xs:simpleType>
</xs:element> % defaultOrNull
else <xs:element name={field.name} type={schemaType} minOccurs={if (field.mandatory) "1" else "0"} /> % defaultOrNull
}
private def generateField(field: ASN1SetField) = field.dataType match {
case t: ASN1IntegerType => dealWithIntOrString(field)
case t: ASN1IA5StringType => dealWithIntOrString(field)
case t: ASN1BooleanType =>
val defaultOrNull = if (t.default.isEmpty) Null else new UnprefixedAttribute("default", t.default.get.toString, Null)
<xs:element name={field.name} type="xs:boolean" minOccurs={if (field.mandatory) "1" else "0"} /> % defaultOrNull
case t: ASN1SetOfType =>
<xs:element name={field.name} type={t.elemType.name + "Type"} minOccurs={if (field.mandatory) "1" else "0"}
maxOccurs={if (t.size != Int.MaxValue) t.size.toString else "unbounded"} />
case _ => <xs:element name={field.name} type={field.dataType.name + "Type"} minOccurs={if (field.mandatory) "1" else "0"} />
}
private def generateKey(identifier: ASN1SetField, operation: String) = {
<xs:key name={identifier.name + "Key_" + operation}>
<xs:selector xpath="." />
<xs:field xpath={"@" + identifier.name} />
</xs:key>
<xs:keyref name={identifier.name + "KeyRef_" + operation} refer={identifier.name + "Key_" + operation}>
<xs:selector xpath="." />
<xs:field xpath={identifier.name} />
</xs:keyref>
}
private def getIdentifierType(identifier: ASN1SetField) = identifier.dataType match {
case t: ASN1IntegerType => if (t.hasRange) identifier.name + identifier.mySet.name + "IdentifierType" else "xs:integer"
case t: ASN1IA5StringType => if (t.hasRange) identifier.name + identifier.mySet.name + "IdentifierType" else "xs:string"
case _ => identifier.dataType.name + "Type"
}
private def generateCreateOrGetResponse(asn1Set: ASN1SetType, operation: String) =
<xs:element name={operation + asn1Set.name}>
<xs:complexType>
<xs:sequence>{asn1Set.fields map generateField}</xs:sequence> {
asn1Set.identifiers map {x =>
<xs:attribute name={x.name} type={getIdentifierType(x)} use="required" />
}
}
</xs:complexType>
{asn1Set.identifiers map(generateKey(_, operation))}
</xs:element>
private def generateSet(asn1Set: ASN1SetType) =
<xs:element name={"set" + asn1Set.name}>
<xs:complexType>
<xs:sequence>{asn1Set.fields.filter(!_.identifier) map generateField}</xs:sequence> {
asn1Set.identifiers map {x =>
<xs:attribute name={x.name} type={getIdentifierType(x)} use="required" />
}
}
</xs:complexType>
</xs:element>
private def generateMissedOperation(asn1Set: ASN1SetType, operation: String) =
<xs:element name={operation + asn1Set.name}>
<xs:complexType> {
asn1Set.identifiers map {x =>
<xs:attribute name={x.name} type={getIdentifierType(x)} use="required" />
}
}
</xs:complexType>
</xs:element>
private def generateIdentifierType(identifiers: List[ASN1SetField]) =
identifiers map {x =>
x.dataType match {
case t: ASN1IntegerType =>
if (t.hasRange)
<xs:simpleType name={x.name + x.mySet.name + "IdentifierType"}>
<xs:restriction base="xs:integer"> {
if (t.minVal != Int.MinValue) <xs:minInclusive value={t.minVal.toString} /> else Null
if (t.maxVal != Int.MaxValue) <xs:maxInclusive value={t.maxVal.toString} /> else Null
}
</xs:restriction>
</xs:simpleType>
else Null
case t: ASN1IA5StringType =>
if (t.hasRange)
<xs:simpleType name={x.name + x.mySet.name + "IdentifierType"}>
<xs:restriction base="xs:string"> {
if (t.minLen != 0) <xs:minLength value={t.minLen.toString} /> else Null
if (t.maxLen != Int.MaxValue) <xs:maxLength value={t.maxLen.toString} /> else Null
}
</xs:restriction>
</xs:simpleType>
else Null
case _ => Null
}
}
private def generateOthers(asn1Module: ASN1Module, mos: List[String]) =
asn1Module.definitions.filterNot(x => mos.exists(_ == x.name)) map {x =>
x match {
case t: ASN1EnumeratedType =>
<xs:simpleType name={t.name + "Type"}>
<xs:restriction base="xs:string"> {
t.values map {x =>
<xs:enumeration value={x._2} />
}
}
</xs:restriction>
</xs:simpleType>
case t: ASN1SetType =>
<xs:complexType name={t.name + "Type"}>
<xs:sequence>{t.fields map generateField}</xs:sequence> {
t.identifiers map {x =>
<xs:attribute name={x.name} type={getIdentifierType(x)} use="required" />
}
}
</xs:complexType> ++
generateIdentifierType(t.identifiers)
}
}
def transform(asn1Module: ASN1Module, mos: List[String]) = {
val namespace = "http://schemas.honnix.com/xxx/UserProvisioning/" + asn1Module.name + "/"
<xs:schema xmlns={namespace} xmlns:ns={namespace} xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace={namespace} elementFormDefault="qualified" attributeFormDefault="unqualified"> {
val elements = mos map {x: String =>
val asn1Set = asn1Module.definitions.find(_.name == x).get.asInstanceOf[ASN1SetType]
generateCreateOrGetResponse(asn1Set, "create") ++ generateSet(asn1Set) ++
generateMissedOperation(asn1Set, "delete") ++ generateMissedOperation(asn1Set, "get") ++
generateCreateOrGetResponse(asn1Set, "getResponse") ++ generateIdentifierType(asn1Set.identifiers)
}
elements ++ generateOthers(asn1Module, mos)
}
</xs:schema>
}
}
@jihao
Copy link

jihao commented Nov 25, 2010

Maybe you can rewrite my schema2wsdl tool using Scala !!!

@honnix
Copy link
Author

honnix commented Nov 25, 2010

You can try to do that. It's very simple.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment