Skip to content

Commit

Permalink
added attributeFormDefault, elementFormDefault, and form support. (GH-26
Browse files Browse the repository at this point in the history
)
  • Loading branch information
eed3si9n committed Jan 27, 2011
1 parent a2927e7 commit 303fee6
Show file tree
Hide file tree
Showing 22 changed files with 216 additions and 103 deletions.
3 changes: 3 additions & 0 deletions cli/src/main/resources/scalaxb.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ object Scalaxb {
def toXML[A](obj: A, namespace: Option[String], elementLabel: Option[String],
scope: NamespaceBinding, typeAttribute: Boolean = false)(implicit format: CanWriteXML[A]): NodeSeq =
format.writes(obj, namespace, elementLabel, scope, typeAttribute)
def toXML[A](obj: A, namespace: Option[String], elementLabel: String, scope: NamespaceBinding)
(implicit format: CanWriteXML[A]): NodeSeq =
toXML(obj, namespace, Some(elementLabel), scope, false)
def toXML[A](obj: A, elementLabel: String, scope: NamespaceBinding)(implicit format: CanWriteXML[A]): NodeSeq =
toXML(obj, None, Some(elementLabel), scope, false)

Expand Down
33 changes: 21 additions & 12 deletions cli/src/main/scala/scalaxb/compiler/xsd/Args.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
*/

package scalaxb.compiler.xsd

trait Args extends Params {
def buildFromXML(typeName: String): String = "fromXML[" + typeName + "]"
def buildFromXML(typeName: String, selector: String): String =
Expand Down Expand Up @@ -83,7 +83,7 @@ trait Args extends Params {
case attr: AttributeDecl =>
val o = attr.copy(use = OptionalUse)
val arg = buildArg(o, buildSelector(o), longAttribute)
if (longAttribute) arg + " map { " + quote(buildNodeName(o)) + " -> _ }"
if (longAttribute) arg + " map { " + quote(buildNodeName(o, false)) + " -> _ }"
else arg
case ref: AttributeRef => buildArgForAttribute(buildAttribute(ref), longAttribute)
case group: AttributeGroupDecl => buildAttributeGroupArg(group, longAttribute)
Expand All @@ -100,7 +100,7 @@ trait Args extends Params {
case _ => error("buildArgForAll unsupported type: " + particle)
}
val arg = buildArg(o, buildSelector(o), longAll)
if (longAll) arg + " map { " + quote(buildNodeName(o)) + " -> _ }"
if (longAll) arg + " map { " + quote(buildNodeName(o, true)) + " -> _ }"
else arg
}

Expand Down Expand Up @@ -174,22 +174,31 @@ trait Args extends Params {

case _ => error("Args: Unsupported type " + typeSymbol.toString)
}

def buildNodeName(elem: ElemDecl): String =
if (elem.namespace == schema.targetNamespace) elem.name
else (elem.namespace map { "{" + _ + "}" } getOrElse {""}) + elem.name

def buildNodeName(attr: AttributeDecl): String =

// scala's <foo/> \ "foo" syntax is not namespace aware, but {ns}foo is useful for long all.
def buildNodeName(elem: ElemDecl, prependNamespace: Boolean): String =
if (elem.global) elem.namespace match {
case None => elem.name
case Some(ns) =>
if (prependNamespace) "{%s}".format(ns) + elem.name
else elem.name
}
else elem.name

// scala's <foo ns:attr1="" /> \ "@{uri}attr1" syntax requires ns, but {uri} should be ommitted for long attr.
def buildNodeName(attr: AttributeDecl, prependNamespace: Boolean): String =
if (attr.global) "@" + (attr.namespace map { "{" + _ + "}" } getOrElse {""}) + attr.name
else if (prependNamespace && attr.qualified) "@" +
(elementNamespace(attr.global, attr.namespace, attr.qualified) map { "{" + _ + "}" } getOrElse {""}) + attr.name
else "@" + attr.name

def buildNodeName(group: AttributeGroupDecl): String =
if (group.namespace == schema.targetNamespace) group.name
else (group.namespace map { "{" + _ + "}" } getOrElse {""}) + group.name

def buildSelector(elem: ElemDecl): String = buildSelector(buildNodeName(elem))
def buildSelector(elem: ElemDecl): String = buildSelector(buildNodeName(elem, false))
def buildSelector(pos: Int): String = "p" + (pos + 1)
def buildSelector(attr: AttributeDecl): String = buildSelector(buildNodeName(attr))
def buildSelector(attr: AttributeDecl): String = buildSelector(buildNodeName(attr, true))
def buildSelector(nodeName: String): String = "(node \\ \"" + nodeName + "\")"

def buildArgForAnyAttribute(parent: ComplexTypeDecl, longAttribute: Boolean): String =
Expand All @@ -199,7 +208,7 @@ trait Args extends Params {
buildArgForAnyAttribute(flattenAttributes(parent.attributes), longAttribute)

def buildArgForAnyAttribute(attributes: List[AttributeLike], longAttribute: Boolean): String = {
def makeCaseEntry(attr: AttributeDecl) = if (attr.global)
def makeCaseEntry(attr: AttributeDecl) = if (attr.global || attr.qualified)
"case scala.xml.PrefixedAttribute(pre, key, value, _) if pre == elem.scope.getPrefix(" +
(attr.namespace map { quote(_) } getOrElse { "null" }) + ") &&" + newline +
indent(8) + "key == " + quote(attr.name) + " => Nil"
Expand Down
47 changes: 32 additions & 15 deletions cli/src/main/scala/scalaxb/compiler/xsd/Decl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ case class XsdContext(
class ParserConfig {
var scope: scala.xml.NamespaceBinding = _
var targetNamespace: Option[String] = None
var elementQualifiedDefault: Boolean = false
var attributeQualifiedDefault: Boolean = false
val topElems = mutable.ListMap.empty[String, ElemDecl]
val elemList = mutable.ListBuffer.empty[ElemDecl]
val topTypes = mutable.ListMap.empty[String, TypeDecl]
Expand Down Expand Up @@ -130,6 +132,8 @@ trait Annotatable {
}

case class SchemaDecl(targetNamespace: Option[String],
elementQualifiedDefault: Boolean,
attributeQualifiedDefault: Boolean,
topElems: Map[String, ElemDecl],
elemList: List[ElemDecl],
topTypes: Map[String, TypeDecl],
Expand Down Expand Up @@ -165,12 +169,16 @@ object SchemaDecl {

config.scope = schema.scope
config.targetNamespace = schema.attribute("targetNamespace").headOption map { _.text }
config.elementQualifiedDefault = schema.attribute("elementFormDefault").headOption map {
_.text == "qualified"} getOrElse {false}
config.attributeQualifiedDefault = schema.attribute("attributeFormDefault").headOption map {
_.text == "qualified"} getOrElse {false}
config.schemas = context.schemas.toList

for (child <- schema.child) child match {
case <element>{ _* }</element> =>
(child \ "@name").headOption foreach { x =>
val elem = ElemDecl.fromXML(child, config.targetNamespace, config)
val elem = ElemDecl.fromXML(child, true, config)
config.topElems += (elem.name -> elem) }

case <attribute>{ _* }</attribute> =>
Expand Down Expand Up @@ -214,6 +222,8 @@ object SchemaDecl {
AnnotationDecl.fromXML(x, config) }

SchemaDecl(config.targetNamespace,
config.elementQualifiedDefault,
config.attributeQualifiedDefault,
immutable.ListMap.empty[String, ElemDecl] ++ config.topElems,
config.elemList.toList,
immutable.ListMap.empty[String, TypeDecl] ++ config.topTypes,
Expand Down Expand Up @@ -306,11 +316,12 @@ object AttributeRef {
case class AttributeDecl(namespace: Option[String],
name: String,
typeSymbol: XsTypeSymbol,
defaultValue: Option[String],
fixedValue: Option[String],
use: AttributeUse,
annotation: Option[AnnotationDecl],
global: Boolean) extends AttributeLike with Annotatable {
defaultValue: Option[String] = None,
fixedValue: Option[String] = None,
use: AttributeUse = OptionalUse,
qualified: Boolean = false,
annotation: Option[AnnotationDecl] = None,
global: Boolean = true) extends AttributeLike with Annotatable {
override def toString = "@" + name
}

Expand Down Expand Up @@ -343,11 +354,13 @@ object AttributeDecl {
case "required" => RequiredUse
case _ => OptionalUse
}
val qualified = (node \ "@form").headOption map {
_.text == "qualifeid" } getOrElse {config.attributeQualifiedDefault}
val annotation = (node \ "annotation").headOption map { x =>
AnnotationDecl.fromXML(x, config) }

val attr = AttributeDecl(config.targetNamespace,
name, typeSymbol, defaultValue, fixedValue, use, annotation,
name, typeSymbol, defaultValue, fixedValue, use, qualified, annotation,
global)
config.attrList += attr
attr
Expand Down Expand Up @@ -410,12 +423,14 @@ case class ElemDecl(namespace: Option[String],
fixedValue: Option[String],
minOccurs: Int,
maxOccurs: Int,
nillable: Option[Boolean],
substitutionGroup: Option[(Option[String], String)],
annotation: Option[AnnotationDecl]) extends Decl with Particle with Annotatable
nillable: Option[Boolean] = None,
global: Boolean = false,
qualified: Boolean = false,
substitutionGroup: Option[(Option[String], String)] = None,
annotation: Option[AnnotationDecl] = None) extends Decl with Particle with Annotatable

object ElemDecl {
def fromXML(node: scala.xml.Node, namespace: Option[String], config: ParserConfig) = {
def fromXML(node: scala.xml.Node, global: Boolean, config: ParserConfig) = {
val name = (node \ "@name").text
var typeSymbol: XsTypeSymbol = XsAnyType
val typeName = (node \ "@type").text
Expand All @@ -441,7 +456,9 @@ object ElemDecl {
case _ =>
}
} // if-else


val qualified = (node \ "@form").headOption map {
_.text == "qualifeid" } getOrElse {config.elementQualifiedDefault}
val defaultValue = (node \ "@default").headOption map { _.text }
val fixedValue = (node \ "@fixed").headOption map { _.text }
val minOccurs = CompositorDecl.buildOccurrence((node \ "@minOccurs").text)
Expand All @@ -452,8 +469,8 @@ object ElemDecl {
val annotation = (node \ "annotation").headOption map { x =>
AnnotationDecl.fromXML(x, config) }

val elem = ElemDecl(namespace,
name, typeSymbol, defaultValue, fixedValue, minOccurs, maxOccurs, nillable,
val elem = ElemDecl(config.targetNamespace,
name, typeSymbol, defaultValue, fixedValue, minOccurs, maxOccurs, nillable, global, qualified,
substitutionGroup, annotation)
config.elemList += elem
if (typeName == "") typeSymbol match {
Expand Down Expand Up @@ -627,7 +644,7 @@ object CompositorDecl {
}) map(node =>
node match {
case <element>{ _* }</element> =>
if ((node \ "@name").headOption.isDefined) ElemDecl.fromXML(node, None, config)
if ((node \ "@name").headOption.isDefined) ElemDecl.fromXML(node, false, config)
else if ((node \ "@ref").headOption.isDefined) ElemRef.fromXML(node, config)
else error("xsd: Unspported content type " + node.toString)
case <choice>{ _* }</choice> => ChoiceDecl.fromXML(node, config)
Expand Down
20 changes: 12 additions & 8 deletions cli/src/main/scala/scalaxb/compiler/xsd/GenProtocol.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ abstract class GenProtocol(val context: XsdContext) extends ContextProcessor {

val name = makeTypeName("XMLProtocol")
val scopeSchemas = context.schemas
def makeScopes(schemas: List[SchemaDecl]): List[(Option[String], String)] = schemas match {
def makeScopes(ss: List[SchemaDecl]): List[(Option[String], String)] = ss match {
case x :: xs =>
x.targetNamespace map { ns =>
val prefix = makePrefix(x.targetNamespace, context)
Expand All @@ -39,13 +39,17 @@ abstract class GenProtocol(val context: XsdContext) extends ContextProcessor {
} getOrElse { makeScopes(xs) }
case _ => Nil
}

val scopes = config.primaryNamespace map { ns =>
((None, ns) :: makeScopes(scopeSchemas.toList) :::
List((Some(XSI_PREFIX) -> XSI_URL)) ).distinct
} getOrElse {makeScopes(scopeSchemas.toList) :::
List((Some(XSI_PREFIX) -> XSI_URL) ).distinct}


val scopes0 = makeScopes(scopeSchemas.toList) ::: List((Some(XSI_PREFIX) -> XSI_URL))
val scopes = config.primaryNamespace match {
case Some(ns) =>
val primaryPair = if (context.schemas forall {_.elementQualifiedDefault}) List((None, ns))
else if (scopes0 exists {_._1 == ns}) Nil
else List((Some("unq"), ns))
(primaryPair ::: scopes0).distinct
case _ => scopes0.distinct
}

val pkg = packageName(config.primaryNamespace, context)
val packageString = pkg map { "package " + _ + newline } getOrElse{""}
val packageImportString = pkg map { "import " + _ + "._" + newline } getOrElse {""}
Expand Down
16 changes: 8 additions & 8 deletions cli/src/main/scala/scalaxb/compiler/xsd/GenSource.scala
Original file line number Diff line number Diff line change
Expand Up @@ -363,10 +363,10 @@ abstract class GenSource(val schema: SchemaDecl,
def makeWritesAttribute = if (attributes.isEmpty) <source></source>
else if (longAttribute) {
val cases = attributes collect {
case attr: AttributeDecl => "case (" + quote(buildNodeName(attr)) + ", _) => " + buildAttributeString(attr)
case attr: AttributeDecl => "case (" + quote(buildNodeName(attr, false)) + ", _) => " + buildAttributeString(attr)
case ref: AttributeRef =>
val attr = buildAttribute(ref)
"case (" + quote(buildNodeName(attr)) + ", _) => " + buildAttributeString(attr)
"case (" + quote(buildNodeName(attr, false)) + ", _) => " + buildAttributeString(attr)
case group: AttributeGroupDecl => "case (" + quote(buildNodeName(group)) + ", _) => " + buildAttributeString(group)
}
val caseString = if (cases.isEmpty) ""
Expand Down Expand Up @@ -794,9 +794,9 @@ object {localName} {{
case ref: ElemRef => buildElement(ref)
} map { elem => toCardinality(elem.minOccurs, elem.maxOccurs) match {
case Optional => "lazy val " + makeParamName(elem.name) + " = " +
wrapperName + ".get(" + quote(buildNodeName(elem)) + ") map { _.as[" + buildTypeName(elem.typeSymbol) + "] }"
wrapperName + ".get(" + quote(buildNodeName(elem, true)) + ") map { _.as[" + buildTypeName(elem.typeSymbol) + "] }"
case _ => "lazy val " + makeParamName(elem.name) + " = " +
wrapperName + "(" + quote(buildNodeName(elem)) + ").as[" + buildTypeName(elem.typeSymbol) + "]"
wrapperName + "(" + quote(buildNodeName(elem, true)) + ").as[" + buildTypeName(elem.typeSymbol) + "]"
}
}
}
Expand All @@ -812,16 +812,16 @@ object {localName} {{
case group: AttributeGroupDecl => (group, Single)
} map { _ match {
case (attr: AttributeDecl, Optional) => "lazy val " + makeParamName(buildParam(attr).name) + " = " +
wrapperName + ".get(" + quote(buildNodeName(attr)) + ") map { _.as[" + buildTypeName(attr.typeSymbol, true) + "] }"
wrapperName + ".get(" + quote(buildNodeName(attr, false)) + ") map { _.as[" + buildTypeName(attr.typeSymbol, true) + "] }"
case (attr: AttributeDecl, Single) => "lazy val " + makeParamName(buildParam(attr).name) + " = " +
wrapperName + "(" + quote(buildNodeName(attr)) + ").as[" + buildTypeName(attr.typeSymbol, true) + "]"
wrapperName + "(" + quote(buildNodeName(attr, false)) + ").as[" + buildTypeName(attr.typeSymbol, true) + "]"

}
}
}

def generateAccessors(params: List[Param], splits: List[SequenceDecl]) = params flatMap {
case param@Param(_, _, ReferenceTypeSymbol(decl@ComplexTypeDecl(_, _, _, _, _, _, _, _)), _, _, _) if
case param@Param(_, _, ReferenceTypeSymbol(decl@ComplexTypeDecl(_, _, _, _, _, _, _, _)), _, _, _, _, _) if
compositorWrapper.contains(decl) &&
splits.contains(compositorWrapper(decl)) =>
val wrapperName = makeParamName(param.name)
Expand Down Expand Up @@ -878,7 +878,7 @@ object {localName} {{

def flattenMixed(decl: ComplexTypeDecl) = if (decl.mixed)
List(ElemDecl(Some(INTERNAL_NAMESPACE), MIXED_PARAM, XsMixed,
None, None, 0, Integer.MAX_VALUE, None, None, None))
None, None, 0, Integer.MAX_VALUE))
else Nil

// def buildAttributes(decl: ComplexTypeDecl): List[AttributeLike] = {
Expand Down
Loading

0 comments on commit 303fee6

Please sign in to comment.