diff --git a/cli/src/main/resources/scalaxb.scala.template b/cli/src/main/resources/scalaxb.scala.template
index 057f59a9e..b9bc00880 100644
--- a/cli/src/main/resources/scalaxb.scala.template
+++ b/cli/src/main/resources/scalaxb.scala.template
@@ -1,7 +1,9 @@
package scalaxb
+import java.time.LocalDateTime
+
+import javax.xml.datatype.{DatatypeFactory, XMLGregorianCalendar}
import scala.xml.{Node, NodeSeq, NamespaceBinding, Elem, UnprefixedAttribute, PrefixedAttribute}
-import javax.xml.datatype.{XMLGregorianCalendar}
import javax.xml.namespace.QName
import javax.xml.bind.DatatypeConverter
@@ -209,6 +211,17 @@ trait XMLStandardTypes {
Helper.stringToXML(obj.toXMLFormat, namespace, elementLabel, scope)
}
+ implicit lazy val __JavaDateTimeXMLFormat: XMLFormat[java.time.LocalDateTime] = new XMLFormat[LocalDateTime] {
+ def localDateTime (d: XMLGregorianCalendar) : LocalDateTime = LocalDateTime.of(d.getYear, d.getMonth, d.getDay, d.getHour, d.getMinute, d.getSecond)
+ def gregorianCalendar (d: LocalDateTime): XMLGregorianCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(d.toString)
+
+ def reads(seq: scala.xml.NodeSeq, stack: List[ElemName]): Either[String, LocalDateTime] =
+ implicitly[XMLFormat[XMLGregorianCalendar]].reads(seq, stack).map(localDateTime)
+
+ override def writes(obj: LocalDateTime, namespace: Option[String], elementLabel: Option[String], scope: NamespaceBinding, typeAttribute: Boolean): NodeSeq =
+ implicitly[XMLFormat[XMLGregorianCalendar]].writes(gregorianCalendar(obj), namespace, elementLabel, scope, typeAttribute)
+ }
+
implicit lazy val __GregorianCalendarXMLWriter: CanWriteXML[java.util.GregorianCalendar] = new CanWriteXML[java.util.GregorianCalendar] {
def writes(obj: java.util.GregorianCalendar, namespace: Option[String], elementLabel: Option[String],
scope: scala.xml.NamespaceBinding, typeAttribute: Boolean): scala.xml.NodeSeq =
diff --git a/cli/src/main/scala/scalaxb/compiler/Config.scala b/cli/src/main/scala/scalaxb/compiler/Config.scala
index 49c1c93ad..cafd84023 100644
--- a/cli/src/main/scala/scalaxb/compiler/Config.scala
+++ b/cli/src/main/scala/scalaxb/compiler/Config.scala
@@ -81,6 +81,7 @@ case class Config(items: Map[String, ConfigEntry]) {
def symbolEncodingStrategy = get[SymbolEncoding.Strategy] getOrElse defaultSymbolEncodingStrategy
def enumNameMaxLength: Int = (get[EnumNameMaxLength] getOrElse defaultEnumNameMaxLength).value
def useLists: Boolean = values contains UseLists
+ def useJavaTime: Boolean = values contains UseJavaTime
private def get[A <: ConfigEntry: Manifest]: Option[A] =
items.get(implicitly[Manifest[A]].runtimeClass.getName).asInstanceOf[Option[A]]
@@ -158,6 +159,7 @@ object ConfigEntry {
case object CapitalizeWords extends ConfigEntry
case class EnumNameMaxLength(value: Int) extends ConfigEntry
case object UseLists extends ConfigEntry
+ case object UseJavaTime extends ConfigEntry
object SymbolEncoding {
sealed abstract class Strategy(val alias: String, val description: String) extends ConfigEntry with Product with Serializable {
diff --git a/cli/src/main/scala/scalaxb/compiler/Module.scala b/cli/src/main/scala/scalaxb/compiler/Module.scala
index 08f07dcff..062ea3a32 100644
--- a/cli/src/main/scala/scalaxb/compiler/Module.scala
+++ b/cli/src/main/scala/scalaxb/compiler/Module.scala
@@ -22,14 +22,16 @@
package scalaxb.compiler
-import java.net.{URI}
-import scala.xml.{Node, Elem, UnprefixedAttribute, NamespaceBinding}
-import scala.xml.factory.{XMLLoader}
+import java.net.URI
+
+import scala.xml.{Elem, NamespaceBinding, Node, UnprefixedAttribute}
+import scala.xml.factory.XMLLoader
import javax.xml.parsers.SAXParser
-import java.io.{File, PrintWriter, Reader, BufferedReader}
-import scala.collection.mutable
+import java.io.{BufferedReader, File, PrintWriter, Reader}
+
import scala.collection.mutable.{ListBuffer, ListMap}
import ConfigEntry._
+import scalaxb.compiler.xsd.ParserConfig
object Snippet {
def apply(snippets: Snippet*): Snippet =
@@ -117,7 +119,7 @@ trait Module {
def includeLocations: Seq[String]
def raw: RawSchema
def location: URI
- def toSchema(context: Context): Schema
+ def toSchema(context: Context, config: ParserConfig): Schema
def swapTargetNamespace(outerNamespace: Option[String], n: Int): Importable
}
@@ -201,11 +203,11 @@ trait Module {
def processReaders[From, To](files: Seq[From], config: Config)
(implicit ev: CanBeRawSchema[From, RawSchema], evTo: CanBeWriter[To]): (CompileSource[From], List[To]) = {
- val source = buildCompileSource(files)
+ val source = buildCompileSource(files, config)
(source, processCompileSource(source, config))
}
- def buildCompileSource[From, To](files: Seq[From])
+ def buildCompileSource[From, To](files: Seq[From], config: Config)
(implicit ev: CanBeRawSchema[From, RawSchema]): CompileSource[From] = {
logger.debug("%s", files.toString())
@@ -213,14 +215,16 @@ trait Module {
val importables0 = ListMap[From, Importable](files map { f =>
f -> toImportable(ev.toURI(f), ev.toRawSchema(f))}: _*)
val importables = ListBuffer[(Importable, From)](files map { f => importables0(f) -> f }: _*)
+ val parserConfig = new ParserConfig
+ parserConfig.useJavaTime = config.useJavaTime
val schemas = ListMap[Importable, Schema](importables map { case (importable, file) =>
- val s = parse(importable, context)
+ val s = parse(importable, context, parserConfig)
(importable, s) } toSeq: _*)
val additionalImportables = ListMap.empty[Importable, File]
// recursively add missing files
- def addMissingFiles(): Unit = {
+ def addMissingFiles(parserConfig: ParserConfig): Unit = {
val current = (importables map {_._1}) ++ additionalImportables.keysIterator.toList
// check for all dependencies before proceeding.
val missings = (current flatMap { importable =>
@@ -239,12 +243,12 @@ trait Module {
added = true
val importable = toImportable(implicitly[CanBeRawSchema[File, RawSchema]].toURI(x),
implicitly[CanBeRawSchema[File, RawSchema]].toRawSchema(x))
- val s = parse(importable, context)
+ val s = parse(importable, context, parserConfig)
schemas(importable) = s
(importable, x) })
- if (added) addMissingFiles()
+ if (added) addMissingFiles(parserConfig)
}
- def processUnnamedIncludes(): Unit = {
+ def processUnnamedIncludes(parserConfig: ParserConfig): Unit = {
logger.debug("processUnnamedIncludes")
val all = (importables.toList map {_._1}) ++ (additionalImportables.toList map {_._1})
val parents: ListBuffer[Importable] = ListBuffer(all filter { !_.includeLocations.isEmpty}: _*)
@@ -270,7 +274,7 @@ trait Module {
logger.debug("processUnnamedIncludes - setting %s's outer namespace to %s", x.location, tnsstr)
count += 1
val swap = x.swapTargetNamespace(tns, count)
- schemas(swap) = parse(swap, context)
+ schemas(swap) = parse(swap, context, parserConfig)
additionalImportables(swap) = new File(swap.location.getPath)
used += x
}
@@ -292,8 +296,8 @@ trait Module {
}
}
- addMissingFiles()
- processUnnamedIncludes()
+ addMissingFiles(parserConfig)
+ processUnnamedIncludes(parserConfig)
CompileSource(context, schemas, importables, additionalImportables,
importables0(files.head).targetNamespace)
}
@@ -426,11 +430,11 @@ trait Module {
def nodeToRawSchema(node: Node): RawSchema
- def parse(importable: Importable, context: Context): Schema
- = importable.toSchema(context)
+ def parse(importable: Importable, context: Context, config: ParserConfig): Schema
+ = importable.toSchema(context, config)
- def parse(location: URI, in: Reader): Schema
- = parse(toImportable(location, readerToRawSchema(in)), buildContext)
+ def parse(location: URI, in: Reader, config: ParserConfig): Schema
+ = parse(toImportable(location, readerToRawSchema(in)), buildContext, config)
def printNodes(nodes: Seq[Node], out: PrintWriter): Unit = {
import scala.xml._
@@ -487,7 +491,7 @@ trait Module {
NamespaceBinding(null, outerNamespace getOrElse null, scope)
def fixSeq(ns: Seq[Node]): Seq[Node] =
for { node <- ns } yield node match {
- case elem: Elem =>
+ case elem: Elem =>
elem.copy(scope = fixScope(elem.scope),
child = fixSeq(elem.child))
case other => other
diff --git a/cli/src/main/scala/scalaxb/compiler/wsdl11/Driver.scala b/cli/src/main/scala/scalaxb/compiler/wsdl11/Driver.scala
index 9ce552719..5babec14f 100644
--- a/cli/src/main/scala/scalaxb/compiler/wsdl11/Driver.scala
+++ b/cli/src/main/scala/scalaxb/compiler/wsdl11/Driver.scala
@@ -31,7 +31,7 @@ import java.net.URI
import scala.xml.Node
import scala.reflect.ClassTag
-import scalaxb.compiler.xsd.{GenProtocol, SchemaDecl, SchemaLite, XsdContext}
+import scalaxb.compiler.xsd.{GenProtocol, ParserConfig, SchemaDecl, SchemaLite, XsdContext}
import scala.util.matching.Regex
@@ -166,14 +166,14 @@ class Driver extends Module { driver =>
schemaLite.includes map { _.schemaLocation }
}
- def toSchema(context: Context): WsdlPair = {
+ def toSchema(context: Context, config: ParserConfig): WsdlPair = {
wsdl foreach { wsdl =>
logger.debug(wsdl.toString)
context.definitions += wsdl
}
val xsd = xsdRawSchema map { x =>
- val schema = SchemaDecl.fromXML(x, context.xsdcontext)
+ val schema = SchemaDecl.fromXML(x, context.xsdcontext, config)
logger.debug(schema.toString)
schema
}
diff --git a/cli/src/main/scala/scalaxb/compiler/wsdl11/GenSource.scala b/cli/src/main/scala/scalaxb/compiler/wsdl11/GenSource.scala
index 1fb0aca47..6a0b390f4 100644
--- a/cli/src/main/scala/scalaxb/compiler/wsdl11/GenSource.scala
+++ b/cli/src/main/scala/scalaxb/compiler/wsdl11/GenSource.scala
@@ -642,7 +642,7 @@ trait {interfaceTypeName} {{
def buildPartArg(part: XPartType, selector: String): String =
(part.typeValue, part.element) match {
case (Some(typeValueQName), _) =>
- val typeSymbol = toTypeSymbol(typeValueQName)
+ val typeSymbol = toTypeSymbol(typeValueQName, config.useJavaTime)
xsdgenerator.buildArg(xsdgenerator.buildTypeName(typeSymbol), selector, Single, None)
case (_, Some(elementQName)) =>
val elem = xsdgenerator.elements(splitTypeName(elementQName))
@@ -718,7 +718,7 @@ trait {interfaceTypeName} {{
def toParamCache(part: XPartType): ParamCache =
part.typeValue map { typeValue =>
val name = camelCase(part.name getOrElse "in")
- ParamCache(name, toTypeSymbol(typeValue), Single, false, false)
+ ParamCache(name, toTypeSymbol(typeValue, config.useJavaTime), Single, false, false)
} getOrElse {
part.element map { element =>
val param = xsdgenerator.buildParam(xsdgenerator.elements(splitTypeName(element))) map {camelCase}
@@ -726,9 +726,9 @@ trait {interfaceTypeName} {{
} getOrElse {sys.error("part does not have either type or element: " + part.toString)}
}
- def toTypeSymbol(qname: javax.xml.namespace.QName): XsTypeSymbol = {
+ def toTypeSymbol(qname: javax.xml.namespace.QName, useJavaTime: Boolean): XsTypeSymbol = {
import scalaxb.compiler.xsd.{ReferenceTypeSymbol, TypeSymbolParser}
- val symbol = TypeSymbolParser.fromQName(qname)
+ val symbol = TypeSymbolParser.fromQName(qname, useJavaTime)
symbol match {
case symbol: ReferenceTypeSymbol =>
val (namespace, typeName) = splitTypeName(qname)
diff --git a/cli/src/main/scala/scalaxb/compiler/xsd/Decl.scala b/cli/src/main/scala/scalaxb/compiler/xsd/Decl.scala
index 66675e4a8..1a44b6963 100644
--- a/cli/src/main/scala/scalaxb/compiler/xsd/Decl.scala
+++ b/cli/src/main/scala/scalaxb/compiler/xsd/Decl.scala
@@ -59,6 +59,7 @@ class ParserConfig {
var targetNamespace: Option[String] = None
var elementQualifiedDefault: Boolean = false
var attributeQualifiedDefault: Boolean = false
+ var useJavaTime: Boolean = false
val topElems = mutable.ListMap.empty[String, ElemDecl]
val elemList = mutable.ListBuffer.empty[ElemDecl]
val topTypes = mutable.ListMap.empty[String, TypeDecl]
@@ -78,16 +79,16 @@ object TypeSymbolParser {
val XML_URI = "http://www.w3.org/XML/1998/namespace"
def fromString(name: String, scope: NamespaceBinding, config: ParserConfig): XsTypeSymbol =
- fromString(splitTypeName(name, scope, config.targetNamespace))
+ fromString(splitTypeName(name, scope, config.targetNamespace), config.useJavaTime)
- def fromQName(qname: javax.xml.namespace.QName): XsTypeSymbol =
- fromString((masked.scalaxb.Helper.nullOrEmpty(qname.getNamespaceURI), qname.getLocalPart))
+ def fromQName(qname: javax.xml.namespace.QName, useJavaTime: Boolean): XsTypeSymbol =
+ fromString((masked.scalaxb.Helper.nullOrEmpty(qname.getNamespaceURI), qname.getLocalPart), useJavaTime)
- def fromString(pair: (Option[String], String)): XsTypeSymbol = {
+ def fromString(pair: (Option[String], String), useJavaTime: Boolean): XsTypeSymbol = {
val (namespace, localPart) = pair
namespace match {
case Some(XML_SCHEMA_URI) =>
- if (XsTypeSymbol.toTypeSymbol.isDefinedAt(localPart)) XsTypeSymbol.toTypeSymbol(localPart)
+ if (XsTypeSymbol.toTypeSymbol(useJavaTime).isDefinedAt(localPart)) XsTypeSymbol.toTypeSymbol(useJavaTime)(localPart)
else ReferenceTypeSymbol(namespace, localPart)
case _ => ReferenceTypeSymbol(namespace, localPart)
}
@@ -147,8 +148,8 @@ case class SchemaDecl(targetNamespace: Option[String],
object SchemaDecl {
def fromXML(node: scala.xml.Node,
- context: XsdContext,
- config: ParserConfig = new ParserConfig) = {
+ context: XsdContext,
+ config: ParserConfig) = {
val schema = (node \\ "schema").headOption.getOrElse {
sys.error("xsd: schema element not found: " + node.toString) }
val targetNamespace = schema.attribute("targetNamespace").headOption map { _.text }
@@ -492,7 +493,7 @@ object SimpleTypeDecl {
def fromXML(node: scala.xml.Node, name: String, family: List[String], config: ParserConfig): SimpleTypeDecl = {
var content: ContentTypeDecl = null
for (child <- node.child) child match {
- case { _* } => content = SimpTypRestrictionDecl.fromXML(child, family, config)
+ case { _* } => content = SimpTypRestrictionDecl.fromXML(child, family, config)
case { _* }
=> content = SimpTypListDecl.fromXML(child, family, config)
case { _* } => content = SimpTypUnionDecl.fromXML(child, config)
case _ =>
diff --git a/cli/src/main/scala/scalaxb/compiler/xsd/Driver.scala b/cli/src/main/scala/scalaxb/compiler/xsd/Driver.scala
index 942af1b58..629b84a54 100644
--- a/cli/src/main/scala/scalaxb/compiler/xsd/Driver.scala
+++ b/cli/src/main/scala/scalaxb/compiler/xsd/Driver.scala
@@ -70,8 +70,8 @@ class Driver extends Module { driver =>
}
val includeLocations: Seq[String] = schemaLite.includes map { _.schemaLocation }
- def toSchema(context: Context): Schema = {
- val schema = SchemaDecl.fromXML(raw, context)
+ def toSchema(context: Context, config: ParserConfig): Schema = {
+ val schema = SchemaDecl.fromXML(raw, context, config)
logger.debug("toSchema: " + schema.toString())
schema
}
diff --git a/cli/src/main/scala/scalaxb/compiler/xsd/XsTypeSymbol.scala b/cli/src/main/scala/scalaxb/compiler/xsd/XsTypeSymbol.scala
index 9c7e511b2..69c7e09e3 100644
--- a/cli/src/main/scala/scalaxb/compiler/xsd/XsTypeSymbol.scala
+++ b/cli/src/main/scala/scalaxb/compiler/xsd/XsTypeSymbol.scala
@@ -1,16 +1,16 @@
/*
* Copyright (c) 2010 e.e d3si9n
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -19,15 +19,15 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-
+
package scalaxb.compiler.xsd
import javax.xml.namespace.QName
trait XsTypeSymbol extends scala.xml.TypeSymbol {
val name: String
-
- override def toString(): String = name
+
+ override def toString(): String = name
}
object XsAnyType extends XsTypeSymbol {
@@ -116,6 +116,7 @@ object XsDuration extends BuiltInSimpleTypeSymbol("javax.xml.datatype.Du
object XsDateTime extends BuiltInSimpleTypeSymbol("javax.xml.datatype.XMLGregorianCalendar") {}
object XsTime extends BuiltInSimpleTypeSymbol("javax.xml.datatype.XMLGregorianCalendar") {}
object XsDate extends BuiltInSimpleTypeSymbol("javax.xml.datatype.XMLGregorianCalendar") {}
+object XsJavaLocalDate extends BuiltInSimpleTypeSymbol("java.time.LocalDateTime")
object XsGYearMonth extends BuiltInSimpleTypeSymbol("javax.xml.datatype.XMLGregorianCalendar") {}
object XsGYear extends BuiltInSimpleTypeSymbol("javax.xml.datatype.XMLGregorianCalendar") {}
object XsGMonthDay extends BuiltInSimpleTypeSymbol("javax.xml.datatype.XMLGregorianCalendar") {}
@@ -160,14 +161,15 @@ object XsUnsignedByte extends BuiltInSimpleTypeSymbol("Int") {}
object XsTypeSymbol {
type =>?[A, B] = PartialFunction[A, B]
val LOCAL_ELEMENT = "http://scalaxb.org/local-element"
-
- val toTypeSymbol: String =>? XsTypeSymbol = {
+
+ def toTypeSymbol(useJavaTime: Boolean): String =>? XsTypeSymbol = {
case "anyType" => XsAnyType
case "anySimpleType" => XsAnySimpleType
case "duration" => XsDuration
case "dateTime" => XsDateTime
case "time" => XsTime
- case "date" => XsDate
+ case "date" if useJavaTime => XsJavaLocalDate
+ case "date" if !useJavaTime => XsDate
case "gYearMonth" => XsGYearMonth
case "gYear" => XsGYear
case "gMonthDay" => XsGMonthDay
@@ -207,6 +209,6 @@ object XsTypeSymbol {
case "short" => XsShort
case "unsignedShort" => XsUnsignedShort
case "byte" => XsByte
- case "unsignedByte" => XsUnsignedByte
- }
+ case "unsignedByte" => XsUnsignedByte
+ }
}
diff --git a/sbt-scalaxb/src/main/scala/sbtscalaxb/ScalaxbKeys.scala b/sbt-scalaxb/src/main/scala/sbtscalaxb/ScalaxbKeys.scala
index f6ea4aa6d..af8c85fad 100644
--- a/sbt-scalaxb/src/main/scala/sbtscalaxb/ScalaxbKeys.scala
+++ b/sbt-scalaxb/src/main/scala/sbtscalaxb/ScalaxbKeys.scala
@@ -46,6 +46,7 @@ trait ScalaxbKeys {
lazy val scalaxbSymbolEncodingStrategy = settingKey[SymbolEncodingStrategy.Value]("Specifies the strategy to encode non-identifier characters in generated class names")
lazy val scalaxbEnumNameMaxLength = settingKey[Int]("Truncates names of enum members longer than this value (default: 50)")
lazy val scalaxbUseLists = settingKey[Boolean]("Declare sequences with concrete type List instead of Seq")
+ lazy val scalaxbUseJavaTime = settingKey[Boolean]("Use Java Time (java.time.*) instead of XMLGregorianCalendar (javax.xml.datatype.*)")
object HttpClientType extends Enumeration {
val None, Dispatch, Gigahorse = Value
diff --git a/sbt-scalaxb/src/main/scala/sbtscalaxb/ScalaxbPlugin.scala b/sbt-scalaxb/src/main/scala/sbtscalaxb/ScalaxbPlugin.scala
index 9d839aaf3..5ff293d01 100644
--- a/sbt-scalaxb/src/main/scala/sbtscalaxb/ScalaxbPlugin.scala
+++ b/sbt-scalaxb/src/main/scala/sbtscalaxb/ScalaxbPlugin.scala
@@ -89,6 +89,7 @@ object ScalaxbPlugin extends sbt.AutoPlugin {
scalaxbSymbolEncodingStrategy := SymbolEncodingStrategy.Legacy151,
scalaxbEnumNameMaxLength := 50,
scalaxbUseLists := false,
+ scalaxbUseJavaTime := false,
scalaxbConfig :=
ScConfig(
Vector(PackageNames(scalaxbCombinedPackageNames.value)) ++
@@ -136,7 +137,8 @@ object ScalaxbPlugin extends sbt.AutoPlugin {
(if (scalaxbCapitalizeWords.value) Vector(CapitalizeWords) else Vector()) ++
Vector(SymbolEncoding.withName(scalaxbSymbolEncodingStrategy.value.toString)) ++
Vector(EnumNameMaxLength(scalaxbEnumNameMaxLength.value)) ++
- (if (scalaxbUseLists.value) Vector(UseLists) else Vector())
+ (if (scalaxbUseLists.value) Vector(UseLists) else Vector()) ++
+ (if (scalaxbUseJavaTime.value) Vector(UseJavaTime) else Vector())
)
))
}