You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by dk...@apache.org on 2019/10/31 14:48:39 UTC
[ws-axiom] 02/25: Initial datatype library code.
This is an automated email from the ASF dual-hosted git repository.
dkulp pushed a commit to branch datatypes
in repository https://gitbox.apache.org/repos/asf/ws-axiom.git
commit d63b90cdbe9f6955401712b1ea6f3b15babc584a
Author: Andreas Veithen <ve...@apache.org>
AuthorDate: Sun Nov 15 19:30:57 2015 +0000
Initial datatype library code.
---
aspects/core-aspects/pom.xml | 5 +
.../org/apache/axiom/core/ContextAccessorImpl.java | 18 +-
.../java/org/apache/axiom/core/CoreElement.java | 5 +
.../org/apache/axiom/core/CoreElementSupport.aj | 17 ++
aspects/fom-aspects/pom.xml | 5 +
.../org/apache/axiom/fom/AbderaDateTimeMixin.aj | 18 +-
{aspects/core-aspects => datatypes}/pom.xml | 35 ++-
.../axiom/datatype/AbstractInvariantType.java | 14 +-
.../org/apache/axiom/datatype/ContextAccessor.java | 7 +-
.../apache/axiom/datatype/DOMContextAccessor.java | 21 +-
.../java/org/apache/axiom/datatype/DOMHelper.java | 19 +-
.../org/apache/axiom/datatype/InvariantType.java | 9 +-
.../main/java/org/apache/axiom/datatype/Type.java | 9 +-
.../datatype/UnexpectedCharacterException.java | 12 +-
.../datatype/UnexpectedEndOfStringException.java | 12 +-
.../AbstractWhitespaceCollapsingInvariantType.java | 46 ++++
.../axiom/datatype/xsd/NoTimeZoneException.java | 6 +-
.../apache/axiom/datatype/xsd/SimpleTimeZone.java | 95 ++++++++
.../org/apache/axiom/datatype/xsd/Temporal.java | 26 ++-
.../apache/axiom/datatype/xsd/TemporalImpl.java | 68 ++++++
.../apache/axiom/datatype/xsd/TemporalType.java | 245 +++++++++++++++++++++
.../java/org/apache/axiom/datatype/xsd/Util.java | 10 +-
.../java/org/apache/axiom/datatype/xsd/XSDate.java | 6 +-
.../org/apache/axiom/datatype/xsd/XSDateImpl.java | 106 +++++++++
.../org/apache/axiom/datatype/xsd/XSDateTime.java | 21 +-
.../apache/axiom/datatype/xsd/XSDateTimeImpl.java | 129 +++++++++++
.../apache/axiom/datatype/xsd/XSDateTimeType.java | 8 +-
.../axiom/datatype/xsd/XSDateTimeTypeImpl.java | 22 +-
.../org/apache/axiom/datatype/xsd/XSDateType.java | 8 +-
.../apache/axiom/datatype/xsd/XSDateTypeImpl.java | 21 +-
.../org/apache/axiom/datatype/xsd/XSQNameType.java | 10 +-
.../apache/axiom/datatype/xsd/XSQNameTypeImpl.java | 97 ++++++++
.../apache/axiom/datatype/xsd/XSStringType.java | 8 +-
.../axiom/datatype/xsd/XSStringTypeImpl.java | 16 +-
.../java/org/apache/axiom/datatype/xsd/XSTime.java | 5 +-
.../org/apache/axiom/datatype/xsd/XSTimeImpl.java | 103 +++++++++
.../org/apache/axiom/datatype/xsd/XSTimeType.java | 8 +-
.../apache/axiom/datatype/xsd/XSTimeTypeImpl.java | 21 +-
.../org/apache/axiom/datatype/DOMHelperTest.java | 42 ++++
.../axiom/datatype/xsd/XSDateTimeTypeTest.java | 53 +++++
implementations/pom.xml | 1 +
pom.xml | 1 +
testing/soap-testsuite/pom.xml | 5 +
.../axiom/ts/soap/ConvertedSOAPSampleContent.java | 57 +++--
44 files changed, 1336 insertions(+), 114 deletions(-)
diff --git a/aspects/core-aspects/pom.xml b/aspects/core-aspects/pom.xml
index a4c1348..afb0952 100644
--- a/aspects/core-aspects/pom.xml
+++ b/aspects/core-aspects/pom.xml
@@ -40,6 +40,11 @@
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>datatypes</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/aspects/core-aspects/src/main/java/org/apache/axiom/core/ContextAccessorImpl.java
similarity index 56%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to aspects/core-aspects/src/main/java/org/apache/axiom/core/ContextAccessorImpl.java
index 900ce36..d28636b 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/aspects/core-aspects/src/main/java/org/apache/axiom/core/ContextAccessorImpl.java
@@ -16,8 +16,20 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.core;
-interface TextTransformer {
- String transform(String in);
+import org.apache.axiom.datatype.ContextAccessor;
+
+final class ContextAccessorImpl implements ContextAccessor<CoreElement,Semantics> {
+ public static final ContextAccessorImpl INSTANCE = new ContextAccessorImpl();
+
+ private ContextAccessorImpl() {}
+
+ public String lookupNamespaceURI(CoreElement element, Semantics semantics, String prefix) {
+ return element.coreLookupNamespaceURI(prefix, semantics);
+ }
+
+ public String lookupPrefix(CoreElement element, Semantics semantics, String namespaceURI) {
+ return element.coreLookupPrefix(namespaceURI, semantics);
+ }
}
diff --git a/aspects/core-aspects/src/main/java/org/apache/axiom/core/CoreElement.java b/aspects/core-aspects/src/main/java/org/apache/axiom/core/CoreElement.java
index a5dd131..be5e79f 100644
--- a/aspects/core-aspects/src/main/java/org/apache/axiom/core/CoreElement.java
+++ b/aspects/core-aspects/src/main/java/org/apache/axiom/core/CoreElement.java
@@ -18,8 +18,11 @@
*/
package org.apache.axiom.core;
+import java.text.ParseException;
import java.util.Iterator;
+import org.apache.axiom.datatype.Type;
+
public interface CoreElement extends CoreChildNode, CoreMixedContentContainer, CoreNamedNode, DeferringParentNode {
/**
* Get the first attribute of this element.
@@ -153,4 +156,6 @@ public interface CoreElement extends CoreChildNode, CoreMixedContentContainer, C
// TODO: wrong Javadoc: null vs. empty string
// TODO: we can support default namespaces!
String coreLookupPrefix(String namespaceURI, Semantics semantics);
+
+ <T> T coreGetValue(Type<T> type, Semantics semantics) throws ParseException;
}
diff --git a/aspects/core-aspects/src/main/java/org/apache/axiom/core/CoreElementSupport.aj b/aspects/core-aspects/src/main/java/org/apache/axiom/core/CoreElementSupport.aj
index 2a271d2..e3e7f32 100644
--- a/aspects/core-aspects/src/main/java/org/apache/axiom/core/CoreElementSupport.aj
+++ b/aspects/core-aspects/src/main/java/org/apache/axiom/core/CoreElementSupport.aj
@@ -18,8 +18,11 @@
*/
package org.apache.axiom.core;
+import java.text.ParseException;
import java.util.Iterator;
+import org.apache.axiom.datatype.Type;
+
public aspect CoreElementSupport {
private CoreAttribute CoreElement.firstAttribute;
@@ -220,4 +223,18 @@ public aspect CoreElementSupport {
// This is basically a hook for OMSourcedElement
public <T> void CoreElement.initSource(ClonePolicy<T> policy, T options, CoreElement other) {
}
+
+ public final <T> T CoreElement.coreGetValue(Type<T> type, Semantics semantics) throws ParseException {
+ Object characterData = coreGetCharacterData(ElementAction.RETURN_NULL);
+ if (characterData == null) {
+ throw new ParseException("Element has mixed content", 0);
+ } else {
+ return type.parse(characterData.toString(), ContextAccessorImpl.INSTANCE, this, semantics);
+ }
+ }
+
+ public final <T> void CoreElement.coreSetValue(Type<T> type, T value, Semantics semantics) {
+ // TODO: actually set value
+ type.format(value, ContextAccessorImpl.INSTANCE, this, semantics);
+ }
}
diff --git a/aspects/fom-aspects/pom.xml b/aspects/fom-aspects/pom.xml
index 3a66c31..e2b467c 100644
--- a/aspects/fom-aspects/pom.xml
+++ b/aspects/fom-aspects/pom.xml
@@ -43,6 +43,11 @@
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>datatypes</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
diff --git a/aspects/fom-aspects/src/main/java/org/apache/axiom/fom/AbderaDateTimeMixin.aj b/aspects/fom-aspects/src/main/java/org/apache/axiom/fom/AbderaDateTimeMixin.aj
index 9bf2142..fb75b3b 100644
--- a/aspects/fom-aspects/src/main/java/org/apache/axiom/fom/AbderaDateTimeMixin.aj
+++ b/aspects/fom-aspects/src/main/java/org/apache/axiom/fom/AbderaDateTimeMixin.aj
@@ -17,19 +17,35 @@
*/
package org.apache.axiom.fom;
+import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import org.apache.abdera.model.AtomDate;
import org.apache.abdera.model.DateTime;
+import org.apache.axiom.datatype.xsd.XSDateTime;
+import org.apache.axiom.datatype.xsd.XSDateTimeType;
import org.apache.axiom.fom.AbderaDateTime;
public aspect AbderaDateTimeMixin {
private AtomDate AbderaDateTime.value;
+ private XSDateTime AbderaDateTime.getXSDateTime() {
+ XSDateTime dateTime;
+ try {
+ dateTime = coreGetValue(XSDateTimeType.INSTANCE, FOMSemantics.INSTANCE);
+ } catch (ParseException ex) {
+ throw new IllegalArgumentException("Invalid Date Format", ex);
+ }
+ if (!dateTime.hasTimeZone()) {
+ throw new IllegalArgumentException("Not a valid RFC3339 date/time value: no time zone");
+ }
+ return dateTime;
+ }
+
public final AtomDate AbderaDateTime.getValue() {
if (value == null) {
- value = AtomDate.valueOf(getText());
+ value = new AtomDate(getXSDateTime().getDate(null));
}
return value;
}
diff --git a/aspects/core-aspects/pom.xml b/datatypes/pom.xml
similarity index 61%
copy from aspects/core-aspects/pom.xml
copy to datatypes/pom.xml
index a4c1348..9111070 100644
--- a/aspects/core-aspects/pom.xml
+++ b/datatypes/pom.xml
@@ -17,31 +17,46 @@
~ specific language governing permissions and limitations
~ under the License.
-->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.ws.commons.axiom</groupId>
- <artifactId>aspects</artifactId>
+ <artifactId>axiom</artifactId>
<version>1.2.16-SNAPSHOT</version>
</parent>
- <artifactId>core-aspects</artifactId>
+ <artifactId>datatypes</artifactId>
<packaging>bundle</packaging>
- <name>Core Aspects</name>
<url>http://ws.apache.org/axiom/</url>
<dependencies>
<dependency>
- <!-- This dependency will eventually go away -->
- <groupId>${project.groupId}</groupId>
- <artifactId>axiom-api</artifactId>
- <version>${project.version}</version>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
</dependency>
<dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
+ <groupId>com.google.truth</groupId>
+ <artifactId>truth</artifactId>
+ <scope>test</scope>
</dependency>
</dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package>*;-noimport:=true</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/AbstractInvariantType.java
similarity index 63%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/AbstractInvariantType.java
index 900ce36..30a4a97 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/AbstractInvariantType.java
@@ -16,8 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype;
-interface TextTransformer {
- String transform(String in);
+import java.text.ParseException;
+
+public abstract class AbstractInvariantType<T> implements InvariantType<T> {
+ public final <S,O> T parse(String literal, ContextAccessor<S,O> contextAccessor, S contextObject, O options) throws ParseException {
+ return parse(literal);
+ }
+
+ public final <S,O> String format(T value, ContextAccessor<S,O> contextAccessor, S contextObject, O options) {
+ return format(value);
+ }
}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/ContextAccessor.java
similarity index 78%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/ContextAccessor.java
index 900ce36..a384eb0 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/ContextAccessor.java
@@ -16,8 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype;
-interface TextTransformer {
- String transform(String in);
+public interface ContextAccessor<T,O> {
+ String lookupNamespaceURI(T contextObject, O options, String prefix);
+ String lookupPrefix(T contextObject, O options, String namespaceURI);
}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/DOMContextAccessor.java
similarity index 52%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/DOMContextAccessor.java
index 900ce36..fc3ed9f 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/DOMContextAccessor.java
@@ -16,8 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype;
-interface TextTransformer {
- String transform(String in);
+import org.w3c.dom.Element;
+
+final class DOMContextAccessor implements ContextAccessor<Element,Void> {
+ static final DOMContextAccessor INSTANCE = new DOMContextAccessor();
+
+ public String lookupNamespaceURI(Element element, Void options, String prefix) {
+ String namespaceURI = element.lookupNamespaceURI(prefix.length() == 0 ? null : prefix);
+ if (namespaceURI != null) {
+ return namespaceURI;
+ } else {
+ return prefix.length() == 0 ? "" : null;
+ }
+ }
+
+ public String lookupPrefix(Element element, Void options, String namespaceURI) {
+ return element.lookupPrefix(namespaceURI.length() == 0 ? null : namespaceURI);
+ }
}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/DOMHelper.java
similarity index 55%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/DOMHelper.java
index 900ce36..46f13cc 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/DOMHelper.java
@@ -16,8 +16,21 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype;
-interface TextTransformer {
- String transform(String in);
+import java.text.ParseException;
+
+import org.w3c.dom.Element;
+
+public final class DOMHelper {
+ private DOMHelper() {}
+
+ public static <T> T getValue(Element element, Type<T> type) throws ParseException {
+ // TODO: using getTextContent here is actually incorrect because it extracts text recursively
+ return type.parse(element.getTextContent(), DOMContextAccessor.INSTANCE, element, null);
+ }
+
+ public static <T> void setValue(Element element, Type<T> type, T value) {
+ element.setTextContent(type.format(value, DOMContextAccessor.INSTANCE, element, null));
+ }
}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/InvariantType.java
similarity index 80%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/InvariantType.java
index 900ce36..88faefe 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/InvariantType.java
@@ -16,8 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype;
-interface TextTransformer {
- String transform(String in);
+import java.text.ParseException;
+
+public interface InvariantType<T> extends Type<T> {
+ T parse(String literal) throws ParseException;
+ String format(T value);
}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/Type.java
similarity index 71%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/Type.java
index 900ce36..b5351b8 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/Type.java
@@ -16,8 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype;
-interface TextTransformer {
- String transform(String in);
+import java.text.ParseException;
+
+public interface Type<T> {
+ <S,O> T parse(String literal, ContextAccessor<S,O> contextAccessor, S contextObject, O options) throws ParseException;
+ <S,O> String format(T value, ContextAccessor<S,O> contextAccessor, S contextObject, O options);
}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/UnexpectedCharacterException.java
similarity index 69%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/UnexpectedCharacterException.java
index 900ce36..ac03ac4 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/UnexpectedCharacterException.java
@@ -16,8 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype;
-interface TextTransformer {
- String transform(String in);
+import java.text.ParseException;
+
+public class UnexpectedCharacterException extends ParseException {
+ private static final long serialVersionUID = 1L;
+
+ public UnexpectedCharacterException(String literal, int errorOffset) {
+ super("Unexpected character '" + literal.charAt(errorOffset) + "'", errorOffset);
+ }
}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/UnexpectedEndOfStringException.java
similarity index 71%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/UnexpectedEndOfStringException.java
index 900ce36..879f78d 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/UnexpectedEndOfStringException.java
@@ -16,8 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype;
-interface TextTransformer {
- String transform(String in);
+import java.text.ParseException;
+
+public class UnexpectedEndOfStringException extends ParseException {
+ private static final long serialVersionUID = 1L;
+
+ public UnexpectedEndOfStringException(String literal) {
+ super("Unexpected end of string", literal.length());
+ }
}
diff --git a/datatypes/src/main/java/org/apache/axiom/datatype/xsd/AbstractWhitespaceCollapsingInvariantType.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/AbstractWhitespaceCollapsingInvariantType.java
new file mode 100644
index 0000000..03cd2d8
--- /dev/null
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/AbstractWhitespaceCollapsingInvariantType.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axiom.datatype.xsd;
+
+import java.text.ParseException;
+
+import org.apache.axiom.datatype.AbstractInvariantType;
+import org.apache.axiom.datatype.UnexpectedEndOfStringException;
+
+abstract class AbstractWhitespaceCollapsingInvariantType<T> extends AbstractInvariantType<T> {
+ public final T parse(String literal) throws ParseException {
+ final int len = literal.length();
+ if (len == 0) {
+ throw new UnexpectedEndOfStringException(literal);
+ }
+ int begin = 0;
+ while (Util.isWhitespace(literal.charAt(begin))) {
+ if (++begin == len) {
+ throw new UnexpectedEndOfStringException(literal);
+ }
+ }
+ int end = len;
+ while (Util.isWhitespace(literal.charAt(end-1))) {
+ end--;
+ }
+ return parse(literal, begin, end);
+ }
+
+ protected abstract T parse(String literal, int begin, int end) throws ParseException;
+}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/NoTimeZoneException.java
similarity index 84%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/xsd/NoTimeZoneException.java
index 900ce36..12d1d69 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/NoTimeZoneException.java
@@ -16,8 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype.xsd;
-interface TextTransformer {
- String transform(String in);
+public class NoTimeZoneException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
}
diff --git a/datatypes/src/main/java/org/apache/axiom/datatype/xsd/SimpleTimeZone.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/SimpleTimeZone.java
new file mode 100644
index 0000000..28dd8bd
--- /dev/null
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/SimpleTimeZone.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axiom.datatype.xsd;
+
+import java.util.Date;
+import java.util.TimeZone;
+
+final class SimpleTimeZone extends TimeZone {
+ private static final long serialVersionUID = 1L;
+
+ private static final SimpleTimeZone[] instances;
+
+ static {
+ instances = new SimpleTimeZone[57];
+ for (int i=0; i<instances.length; i++) {
+ instances[i] = new SimpleTimeZone(30*(-28 + i));
+ }
+ }
+
+ private final int delta;
+
+ SimpleTimeZone(int delta) {
+ this.delta = delta;
+ if (delta == 0) {
+ super.setID("GMT");
+ } else {
+ StringBuilder buffer = new StringBuilder("GMT");
+ buffer.append(delta < 0 ? '-' : '+');
+ delta = Math.abs(delta);
+ append2Digits(buffer, delta/60);
+ buffer.append(':');
+ append2Digits(buffer, delta % 60);
+ super.setID(buffer.toString());
+ }
+ }
+
+ private static void append2Digits(StringBuilder buffer, int value) {
+ buffer.append((char)('0' + value/10));
+ buffer.append((char)('0' + value%10));
+ }
+
+ static SimpleTimeZone getInstance(int delta) {
+ return delta % 30 == 0 ? instances[delta/30 + 28] : new SimpleTimeZone(delta);
+ }
+
+ @Override
+ public int getOffset(int era, int year, int month, int day, int dayOfWeek, int milliseconds) {
+ return getRawOffset();
+ }
+
+ @Override
+ public void setRawOffset(int offsetMillis) {
+ if (getRawOffset() != offsetMillis) {
+ throw new UnsupportedOperationException("Immutable time zone object");
+ }
+ }
+
+ @Override
+ public int getRawOffset() {
+ return delta * 60000;
+ }
+
+ @Override
+ public boolean useDaylightTime() {
+ return false;
+ }
+
+ @Override
+ public boolean inDaylightTime(Date date) {
+ return false;
+ }
+
+ @Override
+ public void setID(String ID) {
+ if (!getID().equals(ID)) {
+ throw new UnsupportedOperationException("Immutable time zone object");
+ }
+ }
+}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/Temporal.java
similarity index 51%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/xsd/Temporal.java
index 900ce36..0d808f6 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/Temporal.java
@@ -16,8 +16,28 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype.xsd;
-interface TextTransformer {
- String transform(String in);
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+public interface Temporal {
+ /**
+ *
+ * @param defaultTimeZone
+ * the time zone to use if this temporal object has no time zone; may be
+ * <code>null</code>
+ * @return
+ * @throws NoTimeZoneException
+ * if this temporal object doesn't have a time zone and no default time zone was
+ * specified
+ */
+ GregorianCalendar getCalendar(TimeZone defaultTimeZone);
+
+ /**
+ * Determine if this temporal object has a time zone.
+ *
+ * @return <code>true</code> if the object has a time zone, <code>false</code> otherwise
+ */
+ boolean hasTimeZone();
}
diff --git a/datatypes/src/main/java/org/apache/axiom/datatype/xsd/TemporalImpl.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/TemporalImpl.java
new file mode 100644
index 0000000..5e381c2
--- /dev/null
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/TemporalImpl.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axiom.datatype.xsd;
+
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+abstract class TemporalImpl implements Temporal {
+ abstract boolean hasDatePart();
+ abstract boolean hasTimePart();
+ abstract boolean isBC();
+ abstract String getAeon();
+ abstract int getYear();
+ abstract int getMonth();
+ abstract int getDay();
+ abstract int getHour();
+ abstract int getMinute();
+ abstract int getSecond();
+ abstract int getNanoSecond();
+ abstract SimpleTimeZone getTimeZone();
+ abstract String getNanoSecondFraction();
+
+ public final GregorianCalendar getCalendar(TimeZone defaultTimeZone) {
+ // TODO: check aeon
+ TimeZone timeZone = getTimeZone();
+ if (timeZone == null) {
+ if (defaultTimeZone == null) {
+ throw new NoTimeZoneException();
+ }
+ timeZone = defaultTimeZone;
+ }
+ GregorianCalendar calendar = new GregorianCalendar(timeZone);
+ if (hasDatePart()) {
+ // TODO: BC
+ // TODO: throw exception if aeon is not null
+ calendar.set(GregorianCalendar.YEAR, getYear());
+ calendar.set(GregorianCalendar.MONTH, getMonth()-1);
+ calendar.set(GregorianCalendar.DAY_OF_MONTH, getDay());
+ }
+ if (hasTimePart()) {
+ calendar.set(GregorianCalendar.HOUR_OF_DAY, getHour());
+ calendar.set(GregorianCalendar.MINUTE, getMinute());
+ calendar.set(GregorianCalendar.SECOND, getSecond());
+ calendar.set(GregorianCalendar.MILLISECOND, getNanoSecond()/1000000);
+ }
+ return calendar;
+ }
+
+ public boolean hasTimeZone() {
+ return getTimeZone() != null;
+ }
+}
diff --git a/datatypes/src/main/java/org/apache/axiom/datatype/xsd/TemporalType.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/TemporalType.java
new file mode 100644
index 0000000..342a449
--- /dev/null
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/TemporalType.java
@@ -0,0 +1,245 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axiom.datatype.xsd;
+
+import java.text.ParseException;
+
+import org.apache.axiom.datatype.UnexpectedCharacterException;
+import org.apache.axiom.datatype.UnexpectedEndOfStringException;
+
+abstract class TemporalType<T> extends AbstractWhitespaceCollapsingInvariantType<T> {
+ abstract boolean hasDatePart();
+ abstract boolean hasTimePart();
+ abstract T createInstance(boolean bc, String aeon, int year, int month, int day, int hour,
+ int minute, int second, int nanoSecond, String nanoSecondFraction,
+ SimpleTimeZone timeZone);
+
+ @Override
+ protected final T parse(String literal, int begin, int end) throws ParseException {
+ int index = begin;
+ boolean bc;
+ String aeon;
+ int year;
+ int month;
+ int day;
+ if (hasDatePart()) {
+ if (literal.charAt(0) == '-') {
+ bc = true;
+ index++;
+ } else {
+ bc = false;
+ }
+ {
+ int digits = countDigits(literal, index, "-", false);
+ if (digits < 4) {
+ throw new UnexpectedCharacterException(literal, index+digits);
+ }
+ if (digits > 4 && literal.charAt(index) == '0') {
+ throw new UnexpectedCharacterException(literal, index);
+ }
+ if (digits > 9) {
+ aeon = literal.substring(index, index+digits-9);
+ index += digits-9;
+ digits = 9;
+ } else {
+ aeon = null;
+ }
+ year = parseDigitsUnchecked(literal, index, digits);
+ if (year == 0) {
+ throw new ParseException("Year can't be zero", index);
+ }
+ index += digits + 1;
+ }
+ month = parseDigitsChecked(literal, index, 2);
+ index += 2;
+ if (index == end) {
+ throw new UnexpectedEndOfStringException(literal);
+ }
+ if (literal.charAt(index) != '-') {
+ throw new UnexpectedCharacterException(literal, index);
+ }
+ index++;
+ day = parseDigitsChecked(literal, index, 2);
+ index += 2;
+ } else {
+ bc = false;
+ aeon = null;
+ year = 0;
+ month = 0;
+ day = 0;
+ }
+ if (hasDatePart() && hasTimePart()) {
+ if (index == end) {
+ throw new UnexpectedEndOfStringException(literal);
+ }
+ if (literal.charAt(index) != 'T') {
+ throw new UnexpectedCharacterException(literal, index);
+ }
+ index++;
+ }
+ int hour;
+ int minute;
+ int second;
+ int nanoSecond;
+ String nanoSecondFraction;
+ if (hasTimePart()) {
+ hour = parseDigitsChecked(literal, index, 2);
+ index += 2;
+ if (index == end) {
+ throw new UnexpectedEndOfStringException(literal);
+ }
+ if (literal.charAt(index) != ':') {
+ throw new UnexpectedCharacterException(literal, index);
+ }
+ index++;
+ minute = parseDigitsChecked(literal, index, 2);
+ index += 2;
+ if (index == end) {
+ throw new UnexpectedEndOfStringException(literal);
+ }
+ if (literal.charAt(index) != ':') {
+ throw new UnexpectedCharacterException(literal, index);
+ }
+ index++;
+ second = parseDigitsChecked(literal, index, 2);
+ index += 2;
+ if (index < end && literal.charAt(index) == '.') {
+ index++;
+ if (index == end) {
+ throw new UnexpectedEndOfStringException(literal);
+ }
+ int digits = countDigits(literal, index, "Z+-", true);
+ if (digits == 0) {
+ if (index == end) {
+ throw new UnexpectedEndOfStringException(literal);
+ } else {
+ throw new UnexpectedCharacterException(literal, index);
+ }
+ }
+ // TODO: we should remove trailing zeros
+ nanoSecond = parseDigitsUnchecked(literal, index, Math.min(digits, 9));
+ if (digits > 9) {
+ nanoSecondFraction = literal.substring(index+9, index+digits-9);
+ } else {
+ for (int i = digits; i < 9; i++) {
+ nanoSecond *= 10;
+ }
+ nanoSecondFraction = null;
+ }
+ index += digits;
+ } else {
+ nanoSecond = 0;
+ nanoSecondFraction = null;
+ }
+ } else {
+ hour = 0;
+ minute = 0;
+ second = 0;
+ nanoSecond = 0;
+ nanoSecondFraction = null;
+ }
+ SimpleTimeZone timeZone;
+ if (index == end) {
+ timeZone = null;
+ } else {
+ int delta;
+ char c = literal.charAt(index);
+ index++;
+ if (c == 'Z') {
+ delta = 0;
+ } else {
+ boolean negative = c == '-';
+ int deltaHours = parseDigitsChecked(literal, index, 2);
+ index += 2;
+ if (index == end) {
+ throw new UnexpectedEndOfStringException(literal);
+ }
+ if (literal.charAt(index) != ':') {
+ throw new UnexpectedCharacterException(literal, index);
+ }
+ index++;
+ int deltaMinutes = parseDigitsChecked(literal, index, 2);
+ index += 2;
+ delta = 60*deltaHours + deltaMinutes;
+ if (negative) {
+ delta = -delta;
+ }
+ }
+ timeZone = SimpleTimeZone.getInstance(delta);
+ }
+ if (index != end) {
+ throw new UnexpectedCharacterException(literal, index);
+ }
+ return createInstance(bc, aeon, year, month, day, hour, minute, second, nanoSecond,
+ nanoSecondFraction, timeZone);
+ }
+
+ private static int countDigits(String literal, int index, String stopChars, boolean allowEndOfString) throws ParseException {
+ final int len = literal.length();
+ int count = 0;
+ while (true) {
+ if (index == len) {
+ if (allowEndOfString) {
+ return count;
+ } else {
+ throw new UnexpectedEndOfStringException(literal);
+ }
+ }
+ char c = literal.charAt(index);
+ if ('0' <= c && c <= '9') {
+ index++;
+ count++;
+ } else if (stopChars.indexOf(c) != -1) {
+ return count;
+ } else {
+ throw new UnexpectedCharacterException(literal, index);
+ }
+ }
+ }
+
+ private static int parseDigitsUnchecked(String literal, int index, int count) {
+ int value = 0;
+ for (; count > 0; count--) {
+ value = 10*value + literal.charAt(index++) - '0';
+ }
+ return value;
+ }
+
+ private static int parseDigitsChecked(String literal, int index, int count) throws ParseException {
+ final int len = literal.length();
+ int value = 0;
+ for (; count > 0; count--) {
+ if (index == len) {
+ throw new UnexpectedEndOfStringException(literal);
+ }
+ char c = literal.charAt(index);
+ if ('0' <= c && c <= '9') {
+ value = 10*value + c - '0';
+ } else {
+ throw new UnexpectedCharacterException(literal, index);
+ }
+ index++;
+ }
+ return value;
+ }
+
+ public final String format(T value) {
+ return value.toString();
+ }
+}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/Util.java
similarity index 80%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/xsd/Util.java
index 900ce36..b244db7 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/Util.java
@@ -16,8 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype.xsd;
-interface TextTransformer {
- String transform(String in);
+final class Util {
+ private Util() {}
+
+ static boolean isWhitespace(char c) {
+ return c == ' ' || c == '\r' || c == '\n' || c == '\t';
+ }
}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDate.java
similarity index 87%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDate.java
index 900ce36..45bef69 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDate.java
@@ -16,8 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype.xsd;
-interface TextTransformer {
- String transform(String in);
+public interface XSDate extends Temporal {
+ XSDateTime getDayStart();
}
diff --git a/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateImpl.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateImpl.java
new file mode 100644
index 0000000..4eb748a
--- /dev/null
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateImpl.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axiom.datatype.xsd;
+
+final class XSDateImpl extends TemporalImpl implements XSDate {
+ private final boolean bc;
+ private final String aeon;
+ private final int year;
+ private final int month;
+ private final int day;
+ private final SimpleTimeZone timeZone;
+
+ XSDateImpl(boolean bc, String aeon, int year, int month, int day, SimpleTimeZone timeZone) {
+ this.bc = bc;
+ this.aeon = aeon;
+ this.year = year;
+ this.month = month;
+ this.day = day;
+ this.timeZone = timeZone;
+ }
+
+ @Override
+ boolean hasDatePart() {
+ return true;
+ }
+
+ @Override
+ boolean hasTimePart() {
+ return false;
+ }
+
+ @Override
+ boolean isBC() {
+ return bc;
+ }
+
+ @Override
+ String getAeon() {
+ return aeon;
+ }
+
+ @Override
+ int getYear() {
+ return year;
+ }
+
+ @Override
+ int getMonth() {
+ return month;
+ }
+
+ @Override
+ int getDay() {
+ return day;
+ }
+
+ @Override
+ int getHour() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ int getMinute() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ int getSecond() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ int getNanoSecond() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ String getNanoSecondFraction() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ SimpleTimeZone getTimeZone() {
+ return timeZone;
+ }
+
+ public XSDateTime getDayStart() {
+ return new XSDateTimeImpl(bc, aeon, year, month, day, 0, 0, 0, 0, null, timeZone);
+ }
+}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateTime.java
similarity index 56%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateTime.java
index 900ce36..dbf45db 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateTime.java
@@ -16,8 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype.xsd;
-interface TextTransformer {
- String transform(String in);
+import java.util.Date;
+import java.util.TimeZone;
+
+public interface XSDateTime extends Temporal {
+ XSDate getDate();
+ XSTime getTime();
+
+ /**
+ * Convert this date/time to a {@link Date} object.
+ *
+ * @param defaultTimeZone
+ * the time zone to use if this date/time has no time zone; may be <code>null</code>
+ * @return the {@link Date} object
+ * @throws NoTimeZoneException
+ * if this date/time doesn't have a time zone and no default time zone was specified
+ */
+ Date getDate(TimeZone defaultTimeZone);
}
diff --git a/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateTimeImpl.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateTimeImpl.java
new file mode 100644
index 0000000..6d33144
--- /dev/null
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateTimeImpl.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axiom.datatype.xsd;
+
+import java.util.Date;
+import java.util.TimeZone;
+
+final class XSDateTimeImpl extends TemporalImpl implements XSDateTime {
+ private final boolean bc;
+ private final String aeon;
+ private final int year;
+ private final int month;
+ private final int day;
+ private final int hour;
+ private final int minute;
+ private final int second;
+ private final int nanoSecond;
+ private final String nanoSecondFraction;
+ private final SimpleTimeZone timeZone;
+
+ XSDateTimeImpl(boolean bc, String aeon, int year, int month, int day, int hour, int minute,
+ int second, int nanoSecond, String nanoSecondFraction, SimpleTimeZone timeZone) {
+ this.bc = bc;
+ this.aeon = aeon;
+ this.year = year;
+ this.month = month;
+ this.day = day;
+ this.hour = hour;
+ this.minute = minute;
+ this.second = second;
+ this.nanoSecond = nanoSecond;
+ this.nanoSecondFraction = nanoSecondFraction;
+ this.timeZone = timeZone;
+ }
+
+ @Override
+ boolean hasDatePart() {
+ return true;
+ }
+
+ @Override
+ boolean hasTimePart() {
+ return true;
+ }
+
+ @Override
+ boolean isBC() {
+ return bc;
+ }
+
+ @Override
+ String getAeon() {
+ return aeon;
+ }
+
+ @Override
+ int getYear() {
+ return year;
+ }
+
+ @Override
+ int getMonth() {
+ return month;
+ }
+
+ @Override
+ int getDay() {
+ return day;
+ }
+
+ @Override
+ int getHour() {
+ return hour;
+ }
+
+ @Override
+ int getMinute() {
+ return minute;
+ }
+
+ @Override
+ int getSecond() {
+ return second;
+ }
+
+ @Override
+ int getNanoSecond() {
+ return nanoSecond;
+ }
+
+ @Override
+ String getNanoSecondFraction() {
+ return nanoSecondFraction;
+ }
+
+ @Override
+ SimpleTimeZone getTimeZone() {
+ return timeZone;
+ }
+
+ public XSDate getDate() {
+ return new XSDateImpl(bc, aeon, year, month, day, timeZone);
+ }
+
+ public XSTime getTime() {
+ return new XSTimeImpl(hour, minute, second, nanoSecond, nanoSecondFraction, timeZone);
+ }
+
+ public Date getDate(TimeZone defaultTimeZone) {
+ // TODO: fast path for dates in the 20th and 21st century
+ return getCalendar(defaultTimeZone).getTime();
+ }
+}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateTimeType.java
similarity index 79%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateTimeType.java
index 900ce36..5b3cbb4 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateTimeType.java
@@ -16,8 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype.xsd;
-interface TextTransformer {
- String transform(String in);
+import org.apache.axiom.datatype.InvariantType;
+
+public interface XSDateTimeType extends InvariantType<XSDateTime> {
+ XSDateTimeType INSTANCE = new XSDateTimeTypeImpl();
}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateTimeTypeImpl.java
similarity index 55%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateTimeTypeImpl.java
index 900ce36..8d19cda 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateTimeTypeImpl.java
@@ -16,8 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype.xsd;
-interface TextTransformer {
- String transform(String in);
+final class XSDateTimeTypeImpl extends TemporalType<XSDateTime> implements XSDateTimeType {
+ @Override
+ boolean hasDatePart() {
+ return true;
+ }
+
+ @Override
+ boolean hasTimePart() {
+ return true;
+ }
+
+ @Override
+ XSDateTime createInstance(boolean bc, String aeon, int year, int month, int day, int hour,
+ int minute, int second, int nanoSecond, String nanoSecondFraction,
+ SimpleTimeZone timeZone) {
+ return new XSDateTimeImpl(bc, aeon, year, month, day, hour, minute, second, nanoSecond,
+ nanoSecondFraction, timeZone);
+ }
}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateType.java
similarity index 84%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateType.java
index 900ce36..e982540 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateType.java
@@ -16,8 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype.xsd;
+
+import org.apache.axiom.datatype.InvariantType;
+
+public interface XSDateType extends InvariantType<XSDate> {
-interface TextTransformer {
- String transform(String in);
}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateTypeImpl.java
similarity index 59%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateTypeImpl.java
index 900ce36..901a798 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSDateTypeImpl.java
@@ -16,8 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype.xsd;
-interface TextTransformer {
- String transform(String in);
+final class XSDateTypeImpl extends TemporalType<XSDate> implements XSDateType {
+ @Override
+ boolean hasDatePart() {
+ return true;
+ }
+
+ @Override
+ boolean hasTimePart() {
+ return false;
+ }
+
+ @Override
+ XSDate createInstance(boolean bc, String aeon, int year, int month, int day, int hour,
+ int minute, int second, int nanoSecond, String nanoSecondFraction,
+ SimpleTimeZone timeZone) {
+ return new XSDateImpl(bc, aeon, year, month, day, timeZone);
+ }
}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSQNameType.java
similarity index 78%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSQNameType.java
index 900ce36..c8497ac 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSQNameType.java
@@ -16,8 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype.xsd;
-interface TextTransformer {
- String transform(String in);
+import javax.xml.namespace.QName;
+
+import org.apache.axiom.datatype.Type;
+
+public interface XSQNameType extends Type<QName> {
+ XSQNameType INSTANCE = new XSQNameTypeImpl();
}
diff --git a/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSQNameTypeImpl.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSQNameTypeImpl.java
new file mode 100644
index 0000000..509dcca
--- /dev/null
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSQNameTypeImpl.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axiom.datatype.xsd;
+
+import java.text.ParseException;
+
+import javax.xml.namespace.QName;
+
+import org.apache.axiom.datatype.ContextAccessor;
+import org.apache.axiom.datatype.UnexpectedCharacterException;
+import org.apache.axiom.datatype.UnexpectedEndOfStringException;
+
+final class XSQNameTypeImpl implements XSQNameType {
+ public <S,O> QName parse(String literal, ContextAccessor<S,O> contextAccessor, S contextObject, O options)
+ throws ParseException {
+ int len = literal.length();
+ int start = -1;
+ int end = -1;
+ int colonIndex = -1;
+ for (int index = 0; index<len; index++) {
+ char c = literal.charAt(index);
+ if (Util.isWhitespace(c)) {
+ if (start != -1 && end == -1) {
+ end = index;
+ }
+ } else {
+ if (start == -1) {
+ start = index;
+ } else if (end != -1) {
+ throw new UnexpectedCharacterException(literal, index);
+ }
+ // TODO: we should check that the literal is a valid NCName
+ if (literal.charAt(index) == ':') {
+ if (colonIndex != -1) {
+ throw new UnexpectedCharacterException(literal, index);
+ }
+ colonIndex = index;
+ }
+ }
+ }
+ if (start == -1) {
+ throw new UnexpectedEndOfStringException(literal);
+ }
+ if (end == -1) {
+ end = len;
+ }
+ String prefix;
+ String localPart;
+ if (colonIndex == -1) {
+ prefix = "";
+ localPart = literal.toString();
+ } else {
+ prefix = literal.substring(start, colonIndex);
+ localPart = literal.substring(colonIndex+1, end);
+ }
+ String namespaceURI = contextAccessor.lookupNamespaceURI(contextObject, options, prefix);
+ if (namespaceURI == null) {
+ throw new ParseException("Unbound namespace prefix \"" + prefix + "\"", 0);
+ }
+ return new QName(namespaceURI, localPart, prefix);
+ }
+
+ public <S,O> String format(QName value, ContextAccessor<S,O> contextAccessor, S contextObject, O options) {
+ String prefix = value.getPrefix();
+ String namespaceURI = value.getNamespaceURI();
+ if (!namespaceURI.equals(contextAccessor.lookupNamespaceURI(contextObject, options, prefix))) {
+ String existingPrefix = contextAccessor.lookupPrefix(contextObject, options, namespaceURI);
+ if (existingPrefix != null) {
+ prefix = existingPrefix;
+ } else {
+ // TODO
+ throw new RuntimeException();
+ }
+ }
+ if (prefix.length() == 0) {
+ return value.getLocalPart();
+ } else {
+ return prefix + ":" + value.getLocalPart();
+ }
+ }
+}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSStringType.java
similarity index 79%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSStringType.java
index 900ce36..068656e 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSStringType.java
@@ -16,8 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype.xsd;
-interface TextTransformer {
- String transform(String in);
+import org.apache.axiom.datatype.InvariantType;
+
+public interface XSStringType extends InvariantType<String> {
+ XSStringType INSTANCE = new XSStringTypeImpl();
}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSStringTypeImpl.java
similarity index 67%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSStringTypeImpl.java
index 900ce36..7c08cc6 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSStringTypeImpl.java
@@ -16,8 +16,18 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype.xsd;
-interface TextTransformer {
- String transform(String in);
+import java.text.ParseException;
+
+import org.apache.axiom.datatype.AbstractInvariantType;
+
+final class XSStringTypeImpl extends AbstractInvariantType<String> implements XSStringType {
+ public String parse(String literal) throws ParseException {
+ return literal;
+ }
+
+ public String format(String value) {
+ return value;
+ }
}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSTime.java
similarity index 89%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSTime.java
index 900ce36..dda1343 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSTime.java
@@ -16,8 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype.xsd;
-interface TextTransformer {
- String transform(String in);
+public interface XSTime extends Temporal {
}
diff --git a/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSTimeImpl.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSTimeImpl.java
new file mode 100644
index 0000000..5b2e347
--- /dev/null
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSTimeImpl.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axiom.datatype.xsd;
+
+final class XSTimeImpl extends TemporalImpl implements XSTime {
+ private final int hour;
+ private final int minute;
+ private final int second;
+ private final int nanoSecond;
+ private final String nanoSecondFraction;
+ private final SimpleTimeZone timeZone;
+
+ XSTimeImpl(int hour, int minute, int second, int nanoSecond, String nanoSecondFraction,
+ SimpleTimeZone timeZone) {
+ this.hour = hour;
+ this.minute = minute;
+ this.second = second;
+ this.nanoSecond = nanoSecond;
+ this.nanoSecondFraction = nanoSecondFraction;
+ this.timeZone = timeZone;
+ }
+
+ @Override
+ boolean hasDatePart() {
+ return false;
+ }
+
+ @Override
+ boolean hasTimePart() {
+ return true;
+ }
+
+ @Override
+ boolean isBC() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ String getAeon() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ int getYear() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ int getMonth() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ int getDay() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ int getHour() {
+ return hour;
+ }
+
+ @Override
+ int getMinute() {
+ return minute;
+ }
+
+ @Override
+ int getSecond() {
+ return second;
+ }
+
+ @Override
+ int getNanoSecond() {
+ return nanoSecond;
+ }
+
+ @Override
+ String getNanoSecondFraction() {
+ return nanoSecondFraction;
+ }
+
+ @Override
+ SimpleTimeZone getTimeZone() {
+ return timeZone;
+ }
+}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSTimeType.java
similarity index 84%
copy from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
copy to datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSTimeType.java
index 900ce36..1d9c8ac 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSTimeType.java
@@ -16,8 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype.xsd;
+
+import org.apache.axiom.datatype.InvariantType;
+
+public interface XSTimeType extends InvariantType<XSTime> {
-interface TextTransformer {
- String transform(String in);
}
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSTimeTypeImpl.java
similarity index 57%
rename from testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
rename to datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSTimeTypeImpl.java
index 900ce36..039945d 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/TextTransformer.java
+++ b/datatypes/src/main/java/org/apache/axiom/datatype/xsd/XSTimeTypeImpl.java
@@ -16,8 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.ts.soap;
+package org.apache.axiom.datatype.xsd;
-interface TextTransformer {
- String transform(String in);
+final class XSTimeTypeImpl extends TemporalType<XSTime> implements XSTimeType {
+ @Override
+ boolean hasDatePart() {
+ return false;
+ }
+
+ @Override
+ boolean hasTimePart() {
+ return true;
+ }
+
+ @Override
+ XSTime createInstance(boolean bc, String aeon, int year, int month, int day, int hour,
+ int minute, int second, int nanoSecond, String nanoSecondFraction,
+ SimpleTimeZone timeZone) {
+ return new XSTimeImpl(hour, minute, second, nanoSecond, nanoSecondFraction, timeZone);
+ }
}
diff --git a/datatypes/src/test/java/org/apache/axiom/datatype/DOMHelperTest.java b/datatypes/src/test/java/org/apache/axiom/datatype/DOMHelperTest.java
new file mode 100644
index 0000000..97e3fab
--- /dev/null
+++ b/datatypes/src/test/java/org/apache/axiom/datatype/DOMHelperTest.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axiom.datatype;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.axiom.datatype.xsd.XSQNameType;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class DOMHelperTest {
+ @Test
+ public void testGetQNameFromElement() throws Exception {
+ Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+ Element element = document.createElementNS("urn:test", "p:elem");
+ element.setTextContent("p:value");
+ QName qname = DOMHelper.getValue(element, XSQNameType.INSTANCE);
+ assertThat(qname.getNamespaceURI()).isEqualTo("urn:test");
+ assertThat(qname.getLocalPart()).isEqualTo("value");
+ assertThat(qname.getPrefix()).isEqualTo("p");
+ }
+}
diff --git a/datatypes/src/test/java/org/apache/axiom/datatype/xsd/XSDateTimeTypeTest.java b/datatypes/src/test/java/org/apache/axiom/datatype/xsd/XSDateTimeTypeTest.java
new file mode 100644
index 0000000..eb81dad
--- /dev/null
+++ b/datatypes/src/test/java/org/apache/axiom/datatype/xsd/XSDateTimeTypeTest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axiom.datatype.xsd;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.fail;
+
+import java.util.Date;
+
+import org.apache.axiom.datatype.UnexpectedEndOfStringException;
+import org.junit.Test;
+
+public class XSDateTimeTypeTest {
+ @Test
+ public void testParse() throws Exception {
+ XSDateTime dateTime = XSDateTimeType.INSTANCE.parse("2003-12-13T18:30:02Z");
+ assertThat(dateTime.getDate(null)).isEqualTo(new Date(1071340202000L));
+ }
+
+ @Test
+ public void testParseTruncated() throws Exception {
+ String literal = "2002-10-10T12:00:00-05:00";
+ for (int i=0; i<literal.length()-1; i++) {
+ if (i == 19) {
+ // This would give a valid literal without time zone
+ continue;
+ }
+ String truncatedLiteral = literal.substring(0, i);
+ try {
+ XSDateTimeType.INSTANCE.parse(truncatedLiteral);
+ fail("Expected UnexpectedEndOfStringException for literal \"" + truncatedLiteral + "\"");
+ } catch (UnexpectedEndOfStringException ex) {
+ // Expected
+ }
+ }
+ }
+}
diff --git a/implementations/pom.xml b/implementations/pom.xml
index 7c6572d..24a48e6 100644
--- a/implementations/pom.xml
+++ b/implementations/pom.xml
@@ -88,6 +88,7 @@
<artifactSet>
<includes>
<include>${project.groupId}:*-aspects</include>
+ <include>${project.groupId}:datatypes</include>
<include>org.aspectj:aspectjrt</include>
</includes>
</artifactSet>
diff --git a/pom.xml b/pom.xml
index a145f0a..529056a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -223,6 +223,7 @@
<module>testing</module>
<module>aspects</module>
<module>implementations</module>
+ <module>datatypes</module>
</modules>
<scm>
diff --git a/testing/soap-testsuite/pom.xml b/testing/soap-testsuite/pom.xml
index 1d299b4..658022a 100644
--- a/testing/soap-testsuite/pom.xml
+++ b/testing/soap-testsuite/pom.xml
@@ -45,6 +45,11 @@
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>datatypes</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
diff --git a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/ConvertedSOAPSampleContent.java b/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/ConvertedSOAPSampleContent.java
index 983487d..36063c9 100644
--- a/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/ConvertedSOAPSampleContent.java
+++ b/testing/soap-testsuite/src/main/java/org/apache/axiom/ts/soap/ConvertedSOAPSampleContent.java
@@ -20,6 +20,7 @@ package org.apache.axiom.ts.soap;
import java.io.InputStream;
import java.io.OutputStream;
+import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
@@ -30,6 +31,8 @@ import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
+import org.apache.axiom.datatype.DOMHelper;
+import org.apache.axiom.datatype.xsd.XSQNameType;
import org.apache.axiom.testing.multiton.Multiton;
import org.apache.axiom.ts.xml.ComputedMessageContent;
import org.w3c.dom.Attr;
@@ -40,15 +43,15 @@ import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
final class ConvertedSOAPSampleContent extends ComputedMessageContent {
- private static Map<String,String> faultCodeMap = new HashMap<String,String>();
+ private static Map<QName,QName> faultCodeMap = new HashMap<>();
static {
faultCodeMap.put(
- SOAPSpec.SOAP12.getSenderFaultCode().getLocalPart(),
- SOAPSpec.SOAP11.getSenderFaultCode().getLocalPart());
+ SOAPSpec.SOAP12.getSenderFaultCode(),
+ SOAPSpec.SOAP11.getSenderFaultCode());
faultCodeMap.put(
- SOAPSpec.SOAP12.getReceiverFaultCode().getLocalPart(),
- SOAPSpec.SOAP11.getReceiverFaultCode().getLocalPart());
+ SOAPSpec.SOAP12.getReceiverFaultCode(),
+ SOAPSpec.SOAP11.getReceiverFaultCode());
}
private final SOAPSample soap12Message;
@@ -112,25 +115,17 @@ final class ConvertedSOAPSampleContent extends ComputedMessageContent {
child = nextChild;
}
} else if (type == SOAPFaultChild.CODE) {
- final Element value = getChild(element, SOAPFaultChild.VALUE);
- element.setTextContent(transform(value.getTextContent(), new TextTransformer() {
- @Override
- public String transform(String in) {
- int idx = in.indexOf(':');
- if (idx == -1) {
- return in;
- }
- String prefix = in.substring(0, idx);
- if (!SOAPSpec.SOAP12.getEnvelopeNamespaceURI().equals(value.lookupNamespaceURI(prefix))) {
- return in;
- }
- String newCode = faultCodeMap.get(in.substring(idx+1));
- if (newCode == null) {
- return in;
- }
- return prefix + ":" + newCode;
- }
- }));
+ Element value = getChild(element, SOAPFaultChild.VALUE);
+ String[] whitespace = getSurroundingWhitespace(value.getTextContent());
+ QName qname;
+ try {
+ qname = DOMHelper.getValue(value, XSQNameType.INSTANCE);
+ } catch (ParseException ex) {
+ throw new Error(ex);
+ }
+ QName newQName = faultCodeMap.get(qname);
+ DOMHelper.setValue(element, XSQNameType.INSTANCE, newQName == null ? qname : newQName);
+ element.setTextContent(reapplyWhitespace(element.getTextContent(), whitespace));
} else if (type == SOAPFaultChild.REASON) {
Element text = getChild(element, SOAPFaultChild.TEXT);
element.setTextContent(text.getTextContent());
@@ -210,19 +205,19 @@ final class ConvertedSOAPSampleContent extends ComputedMessageContent {
return " \r\n\t".indexOf(c) != -1;
}
- private static String transform(String text, TextTransformer transformer) {
+ private static String[] getSurroundingWhitespace(String text) {
int start = 0;
while (isWhitespace(text.charAt(start))) {
- if (++start == text.length()) {
- return text;
- }
+ start++;
}
int end = text.length();
while (isWhitespace(text.charAt(end-1))) {
end--;
}
- return text.substring(0, start)
- + transformer.transform(text.substring(start, end))
- + text.substring(end);
+ return new String[] { text.substring(0, start), text.substring(end) };
+ }
+
+ private static String reapplyWhitespace(String text, String[] surroundingWhitespace) {
+ return surroundingWhitespace[0] + text + surroundingWhitespace[1];
}
}